Skip to content

Commit 3c8d678

Browse files
Antoine Doubovetzkyfacebook-github-bot
authored andcommitted
Extract visit function to parsers/utils (#34946)
Summary: This PR is a task from #34872: > Extract the visit function in a shared function in the parsers/utils.js folder. Use the new function in the Flow and TypeScript parsers. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [Internal] [Changed] - Extract the visit function in a shared function in the parsers/utils.js Pull Request resolved: #34946 Test Plan: I tested using jest, flow and eslint commands. Reviewed By: NickGerleman Differential Revision: D40276462 Pulled By: cipolleschi fbshipit-source-id: 299cc2a3aa65a9757b217192a13838d037c497a1
1 parent 74fff88 commit 3c8d678

File tree

8 files changed

+141
-64
lines changed

8 files changed

+141
-64
lines changed

packages/react-native-codegen/src/parsers/__tests__/utils-test.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
const {
1515
extractNativeModuleName,
1616
createParserErrorCapturer,
17+
visit,
1718
} = require('../utils.js');
1819
const {ParserError} = require('../errors');
1920

@@ -115,3 +116,107 @@ describe('createParserErrorCapturer', () => {
115116
});
116117
});
117118
});
119+
120+
describe('visit', () => {
121+
describe('when the astNode is null', () => {
122+
it("doesn't call the visitor function", () => {
123+
const visitorFunction = jest.fn();
124+
const visitor = {
125+
itemType: visitorFunction,
126+
};
127+
128+
const astNode = null;
129+
130+
visit(astNode, visitor);
131+
132+
expect(visitorFunction).not.toHaveBeenCalled();
133+
});
134+
});
135+
136+
describe('when the astNode is not an object', () => {
137+
it("doesn't call the visitor function", () => {
138+
const visitorFunction = jest.fn();
139+
const visitor = {
140+
itemType: visitorFunction,
141+
};
142+
143+
const astNode = 'astNode';
144+
145+
visit(astNode, visitor);
146+
147+
expect(visitorFunction).not.toHaveBeenCalled();
148+
});
149+
});
150+
151+
describe('when the astNode is an object', () => {
152+
describe("when the astNode has a string type that doesn't exist in the visitor object", () => {
153+
it("doesn't call the visitor function", () => {
154+
const visitorFunction = jest.fn();
155+
const visitor = {
156+
itemType: visitorFunction,
157+
};
158+
159+
const astNode = {type: 'itemTypeNotInVisitor'};
160+
161+
visit(astNode, visitor);
162+
163+
expect(visitorFunction).not.toHaveBeenCalled();
164+
});
165+
});
166+
167+
describe('when the astNode has a string type that exists in the visitor object', () => {
168+
it("doesn't call the visitor function", () => {
169+
const visitorFunction = jest.fn();
170+
const visitor = {
171+
itemType: visitorFunction,
172+
};
173+
174+
const astNode = {type: 'itemType'};
175+
176+
visit(astNode, visitor);
177+
178+
expect(visitorFunction).toHaveBeenCalledTimes(1);
179+
});
180+
});
181+
182+
describe("when the astNode doesn't have a string type", () => {
183+
it('iterates on every values of the astNode', () => {
184+
const visitorFunction = jest.fn();
185+
const visitor = {
186+
itemType1: visitorFunction,
187+
itemType2: visitorFunction,
188+
};
189+
190+
const astNode = {
191+
firstChildNode: {type: 'itemType1'},
192+
secondChildNode: {type: 'itemType2'},
193+
thirdChildNode: {type: 'itemType3'},
194+
};
195+
196+
visit(astNode, visitor);
197+
198+
expect(visitorFunction).toHaveBeenCalledTimes(2);
199+
});
200+
});
201+
});
202+
203+
describe('when the astNode is an array', () => {
204+
it('iterates on every values of the astNode', () => {
205+
const visitorFunction = jest.fn();
206+
const visitor = {
207+
itemType1: visitorFunction,
208+
itemType2: visitorFunction,
209+
};
210+
211+
const astNode = [
212+
{type: 'itemType1'},
213+
{type: 'itemType2'},
214+
{type: 'itemType3'},
215+
];
216+
217+
visit(astNode, visitor);
218+
219+
expect(visitorFunction).toHaveBeenCalledTimes(2);
220+
});
221+
});
222+
});

packages/react-native-codegen/src/parsers/flow/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ const fs = require('fs');
1717
const {
1818
extractNativeModuleName,
1919
createParserErrorCapturer,
20+
visit,
2021
} = require('../utils.js');
2122
const {buildComponentSchema} = require('./components');
2223
const {wrapComponentSchema} = require('./components/schema');
2324
const {buildModuleSchema} = require('./modules');
2425
const {wrapModuleSchema} = require('../parsers-commons');
25-
const {visit, isModuleRegistryCall} = require('./utils');
26+
const {isModuleRegistryCall} = require('./utils');
2627
const invariant = require('invariant');
2728

2829
function getConfigType(

packages/react-native-codegen/src/parsers/flow/modules/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ import type {NativeModuleTypeAnnotation} from '../../../CodegenSchema.js';
2727
const {nullGuard} = require('../../parsers-utils');
2828

2929
const {throwIfMoreThanOneModuleRegistryCalls} = require('../../error-utils');
30+
const {visit} = require('../../utils');
3031
const {
3132
resolveTypeAnnotation,
3233
getTypes,
33-
visit,
3434
isModuleRegistryCall,
3535
} = require('../utils.js');
3636
const {

packages/react-native-codegen/src/parsers/flow/utils.js

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -116,35 +116,6 @@ function getValueFromTypes(value: ASTNode, types: TypeDeclarationMap): ASTNode {
116116
return value;
117117
}
118118

119-
// TODO(T71778680): Flow-type ASTNodes.
120-
function visit(
121-
astNode: $FlowFixMe,
122-
visitor: {
123-
[type: string]: (node: $FlowFixMe) => void,
124-
},
125-
) {
126-
const queue = [astNode];
127-
while (queue.length !== 0) {
128-
let item = queue.shift();
129-
130-
if (!(typeof item === 'object' && item != null)) {
131-
continue;
132-
}
133-
134-
if (
135-
typeof item.type === 'string' &&
136-
typeof visitor[item.type] === 'function'
137-
) {
138-
// Don't visit any children
139-
visitor[item.type](item);
140-
} else if (Array.isArray(item)) {
141-
queue.push(...item);
142-
} else {
143-
queue.push(...Object.values(item));
144-
}
145-
}
146-
}
147-
148119
// TODO(T71778680): Flow-type ASTNodes.
149120
function isModuleRegistryCall(node: $FlowFixMe): boolean {
150121
if (node.type !== 'CallExpression') {
@@ -188,6 +159,5 @@ module.exports = {
188159
getValueFromTypes,
189160
resolveTypeAnnotation,
190161
getTypes,
191-
visit,
192162
isModuleRegistryCall,
193163
};

packages/react-native-codegen/src/parsers/typescript/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ const fs = require('fs');
1616
const {
1717
extractNativeModuleName,
1818
createParserErrorCapturer,
19+
visit,
1920
} = require('../utils.js');
2021
const {buildComponentSchema} = require('./components');
2122
const {wrapComponentSchema} = require('./components/schema');
2223
const {buildModuleSchema} = require('./modules');
2324
const {wrapModuleSchema} = require('../parsers-commons');
2425

25-
const {visit, isModuleRegistryCall} = require('./utils');
26+
const {isModuleRegistryCall} = require('./utils');
2627
const invariant = require('invariant');
2728

2829
function getConfigType(

packages/react-native-codegen/src/parsers/typescript/modules/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ import type {NativeModuleTypeAnnotation} from '../../../CodegenSchema.js';
2727
const {nullGuard} = require('../../parsers-utils');
2828

2929
const {throwIfMoreThanOneModuleRegistryCalls} = require('../../error-utils');
30+
const {visit} = require('../../utils');
3031
const {
3132
resolveTypeAnnotation,
3233
getTypes,
33-
visit,
3434
isModuleRegistryCall,
3535
} = require('../utils.js');
3636
const {

packages/react-native-codegen/src/parsers/typescript/utils.js

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -109,35 +109,6 @@ function resolveTypeAnnotation(
109109
};
110110
}
111111

112-
// TODO(T108222691): Use flow-types for @babel/parser
113-
function visit(
114-
astNode: $FlowFixMe,
115-
visitor: {
116-
[type: string]: (node: $FlowFixMe) => void,
117-
},
118-
) {
119-
const queue = [astNode];
120-
while (queue.length !== 0) {
121-
let item = queue.shift();
122-
123-
if (!(typeof item === 'object' && item != null)) {
124-
continue;
125-
}
126-
127-
if (
128-
typeof item.type === 'string' &&
129-
typeof visitor[item.type] === 'function'
130-
) {
131-
// Don't visit any children
132-
visitor[item.type](item);
133-
} else if (Array.isArray(item)) {
134-
queue.push(...item);
135-
} else {
136-
queue.push(...Object.values(item));
137-
}
138-
}
139-
}
140-
141112
// TODO(T108222691): Use flow-types for @babel/parser
142113
function isModuleRegistryCall(node: $FlowFixMe): boolean {
143114
if (node.type !== 'CallExpression') {
@@ -180,6 +151,5 @@ function isModuleRegistryCall(node: $FlowFixMe): boolean {
180151
module.exports = {
181152
resolveTypeAnnotation,
182153
getTypes,
183-
visit,
184154
isModuleRegistryCall,
185155
};

packages/react-native-codegen/src/parsers/utils.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,37 @@ function createParserErrorCapturer(): [
5454
return [errors, guard];
5555
}
5656

57+
// TODO(T108222691): Use flow-types for @babel/parser
58+
function visit(
59+
astNode: $FlowFixMe,
60+
visitor: {
61+
[type: string]: (node: $FlowFixMe) => void,
62+
},
63+
) {
64+
const queue = [astNode];
65+
while (queue.length !== 0) {
66+
let item = queue.shift();
67+
68+
if (!(typeof item === 'object' && item != null)) {
69+
continue;
70+
}
71+
72+
if (
73+
typeof item.type === 'string' &&
74+
typeof visitor[item.type] === 'function'
75+
) {
76+
// Don't visit any children
77+
visitor[item.type](item);
78+
} else if (Array.isArray(item)) {
79+
queue.push(...item);
80+
} else {
81+
queue.push(...Object.values(item));
82+
}
83+
}
84+
}
85+
5786
module.exports = {
5887
extractNativeModuleName,
5988
createParserErrorCapturer,
89+
visit,
6090
};

0 commit comments

Comments
 (0)