Skip to content

Commit 4607130

Browse files
committed
Working on traversing child import files, currently only able to gather paths for child import files. Will continue to work on how to traverse remaining files in client directory.
1 parent e8f27f4 commit 4607130

File tree

5 files changed

+138
-112
lines changed

5 files changed

+138
-112
lines changed

extension.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const vscode = require('vscode');
22
const { createPanel } = require('./src/panel');
3-
const { grabFile } = require('./src/parser');
3+
const { Parser } = require('./src/parser');
44

55
// This method is called when your extension is activated
66
// Your extension is activated the very first time the command is executed
@@ -17,8 +17,10 @@ function activate(context) {
1717
createPanel(context);
1818
});
1919

20-
vscode.commands.registerCommand('myExtension.pickFile', () => {
21-
grabFile();
20+
vscode.commands.registerCommand('myExtension.pickFile', async () => {
21+
const tree = new Parser();
22+
const file = await vscode.window.showOpenDialog({ canSelectFolders: true, canSelectFiles: true, canSelectMany: true });
23+
tree.grabFile(file);
2224
});
2325

2426
context.subscriptions.push(disposable, result);

src/getNonce.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function getNonce() {
2+
let text = "";
3+
const possible =
4+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
5+
for (let i = 0; i < 32; i++) {
6+
text += possible.charAt(Math.floor(Math.random() * possible.length));
7+
}
8+
return text;
9+
}
10+
11+
module.exports = { getNonce }

src/parser.js

Lines changed: 111 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,136 @@
11
const vscode = require('vscode');
2-
const fs = require('fs');
3-
const path = require('path');
2+
const fs = require('fs')
3+
const path = require('path')
44
const babel = require('@babel/parser');
5-
6-
let ast;
7-
async function grabFile() {
8-
try {
9-
const file = await vscode.window.showOpenDialog({ canSelectFolders: true, canSelectFiles: true, canSelectMany: true });
10-
console.log('file path', file[0].path);
11-
const name = path.basename(file[0].path);
12-
console.log('name of file', name);
13-
ast = await babel.parse(
14-
fs.readFileSync(path.resolve(file[0].path), 'utf-8'),
15-
{
16-
sourceType: 'module',
17-
tokens: true,
18-
plugins: ['jsx', 'typescript'],
19-
});
20-
// console.log('ast', ast);
21-
const result = await traverseAST(ast);
22-
console.log('res', result);
23-
// const tokens = ast.tokens;
24-
// console.log('tokens are:', tokens);
25-
} catch (error) {
26-
console.error(`Error processing file: ${error}`)
5+
const getNonce = require('./getNonce.js');
6+
const Tree = require('./treeTemplates/tree.js')
7+
8+
class Parser {
9+
constructor() {
10+
this.ast = undefined;
11+
this.entryFile = undefined;
12+
this.arrList = [];
2713
}
28-
}
29-
30-
// create a set to reduce redundancy in console logs during recursive call
31-
const processedNodes = new Set();
32-
33-
// traverse the ast nodes, passing in node
34-
async function traverseAST(node) {
35-
// identify which are jsx elements type and then extract info about them (like the component name) and store it in var
36-
if (node.type === 'ImportDeclaration' && !processedNodes.has(node)) {
37-
processedNodes.add(node);
38-
// console.log('JSX Node', node);
3914

40-
// im guessing that jsx elements will never contain the use client or hook declaration, so i wouldnt need to call the functions here
41-
42-
// property on node to obtain component name (could be tag or component name)
43-
const elementName = node.source.value;
44-
if(elementName.startsWith('./') || elementName.startsWith('../')) console.log('file path:', elementName);
45-
46-
47-
if (node.children) {
48-
// if node children exist, then recursively call the child nodes with this func
49-
for (const child of node.children) {
50-
await traverseAST(child);
15+
async grabFile(file) {
16+
try {
17+
// const file = await vscode.window.showOpenDialog({ canSelectFolders: true, canSelectFiles: true, canSelectMany: true });
18+
// if(typeof(file) !== 'string'){
19+
if (typeof (file) !== 'string') {
20+
file = path.resolve(file[0].path)
5121
}
22+
this.ast = babel.parse(
23+
fs.readFileSync(file, 'utf-8'),
24+
{
25+
sourceType: 'module',
26+
tokens: true,
27+
plugins: ['jsx', 'typescript'],
28+
});
29+
await this.traverseAST(this.ast);
30+
31+
console.log('Result of arrList: ', this.arrList);
32+
33+
} catch (error) {
34+
console.error(`Error processing file: ${error}`)
5235
}
53-
} else if (!processedNodes.has(node)) {
54-
processedNodes.add(node);
36+
}
5537

56-
// call the function to determine if it is a client component and store it in var
57-
// const isClientComp = await checkForClientString(node);
58-
// const isReactHook = await checkReactHooks(node);
5938

60-
// recursively iterate through the other non-jsx types if the jsx node children doesnt exist
61-
for (const key in node) {
62-
if (node[key] && typeof node[key] === 'object' && key !== 'tokens') {
63-
await traverseAST(node[key]);
39+
// traverse the ast nodes, passing in node
40+
traverseAST(node) {
41+
if (node.type === 'ImportDeclaration') {
42+
// processedNodes.add(node);
43+
// console.log('JSX Node', node);
44+
45+
// extract file name path
46+
const elementName = node.source.value;
47+
if (elementName.startsWith('./') || elementName.startsWith('../')) {
48+
console.log('file path:', elementName)
49+
// processedNodes.add(elementName)
50+
console.log('node import: ', node);
51+
this.arrList.push(node.source.value);
52+
return this.grabFile(node.source.value);
53+
};
54+
55+
/* this code only works for JSXElement types: has prop of .children, but not the one above
56+
if (node.children) {
57+
// if node children exist, then recursively call the child nodes with this func
58+
for (const child of node.children) {
59+
await traverseAST(child);
60+
}
61+
}
62+
*/
63+
} else {
64+
// const isClientComp = await checkForClientString(node);
65+
// const isReactHook = await checkReactHooks(node);
66+
67+
// recursively iterate through the other non-jsx types if the jsx node children doesnt exist
68+
for (const key in node) {
69+
if (node[key] && typeof node[key] === 'object' && key !== 'tokens') {
70+
this.traverseAST(node[key]);
71+
}
6472
}
6573
}
6674
}
67-
return processedNodes;
68-
}
69-
70-
// function to determine server or client component (can look for 'use client' and 'hooks')
71-
72-
// also might want to consider functionality for child components of the current node to be classifed as client component (except for server clients rendered tree)
7375

74-
function checkForClientString(node) {
75-
if (node.type === 'Directive') {
76-
console.log('node', node);
76+
// function to determine server or client component (can look for 'use client' and 'hooks')
77+
checkForClientString(node) {
78+
if (node.type === 'Directive') {
79+
console.log('node', node);
7780

78-
// access the value property of the Directive node
79-
console.log('Directive Value:', node.value);
81+
// access the value property of the Directive node
82+
console.log('Directive Value:', node.value);
8083

81-
// check if the node.value is a 'DirectiveLiteral' node
82-
if (node.value && node.value.type === 'DirectiveLiteral') {
84+
// check if the node.value is a 'DirectiveLiteral' node
85+
if (node.value && node.value.type === 'DirectiveLiteral') {
8386

84-
// check the value to see if it is 'use client'
85-
if (typeof node.value.value === 'string' && node.value.value.trim() === 'use client') {
86-
// access the value property of the 'DirectiveLiteral' node
87-
console.log('DirectiveLiteral Value:', node.value.value);
87+
// check the value to see if it is 'use client'
88+
if (typeof node.value.value === 'string' && node.value.value.trim() === 'use client') {
89+
// access the value property of the 'DirectiveLiteral' node
90+
console.log('DirectiveLiteral Value:', node.value.value);
8891

89-
// might need to do something else here to make it known as client type
90-
console.log(`this node above has 'use client': `, true);
91-
return true;
92+
// might need to do something else here to make it known as client type
93+
console.log(`this node above has 'use client': `, true);
94+
return true;
95+
}
9296
}
9397
}
98+
return false;
9499
}
95-
return false;
96-
}
97100

98-
function checkReactHooks(node) {
99-
// for just the mvp, look up for the FIRST client component and make every child as a client component
100-
101-
// function to determine if component uses react hooks (this only checks if its BEING CALLED IN COMPONENT, not IMPORTED)
102-
// console.log('node', node);
103-
if (node.type === 'CallExpression') {
104-
console.log('nodeCall', node)
105-
if (node.callee && node.callee.name) {
106-
if (node.callee.name.startsWith('use')) {
107-
// if the node.type is CallExpression (dealing with function or method call) (callee is prop on callexpression - an identifier), return true
108-
console.log('node.callee', node.callee);
109-
console.log('Node with Hook', node.callee.name);
110-
console.log(`this node above uses hooks: `, true);
111-
return true;
101+
checkReactHooks(node) {
102+
// for just the mvp, look up for the FIRST client component and make every child as a client component
103+
104+
// function to determine if component uses react hooks (this only checks if its BEING CALLED IN COMPONENT)
105+
if (node.type === 'CallExpression') {
106+
console.log('nodeCall', node)
107+
if (node.callee && node.callee.name) {
108+
if (node.callee.name.startsWith('use')) {
109+
// if the node.type is CallExpression (dealing with function or method call) (callee is prop on callexpression - an identifier), return true
110+
console.log('node.callee', node.callee);
111+
console.log('Node with Hook', node.callee.name);
112+
console.log(`this node above uses hooks: `, true);
113+
return true;
114+
}
112115
}
113116
}
114-
}
115117

116-
// function to determine if hooks are being IMPORTED
117-
// if (node.type === 'ImportDeclaration') {
118-
// console.log('node import', node);
119-
// if (node.specifiers) {
120-
// // filter through the array to see which ones uses hooks
121-
// const clientNodes = node.specifiers.filter((nodeImport) => {
122-
// return nodeImport.type === 'ImportSpecifier' && nodeImport.imported.name.startsWith('use');
123-
// });
124-
// // mapped over to console log the name of hook
125-
// clientNodes.map((nodeImport) => console.log('Names of Hooks', nodeImport.imported.name));
126-
// console.log(clientNodes);
127-
// // we'll wanna change this to use it somehow
128-
// return clientNodes;
129-
// }
130-
return false;
118+
// function to determine if hooks are being IMPORTED
119+
// if (node.type === 'ImportDeclaration') {
120+
// console.log('node import', node);
121+
// if (node.specifiers) {
122+
// // filter through the array to see which ones uses hooks
123+
// const clientNodes = node.specifiers.filter((nodeImport) => {
124+
// return nodeImport.type === 'ImportSpecifier' && nodeImport.imported.name.startsWith('use');
125+
// });
126+
// // mapped over to console log the name of hook
127+
// clientNodes.map((nodeImport) => console.log('Names of Hooks', nodeImport.imported.name));
128+
// console.log(clientNodes);
129+
// // we'll wanna change this to use it somehow
130+
// return clientNodes;
131+
// }
132+
return false;
133+
}
131134
}
132135

133136
// function to determine if the client component imports server components or call server hooks/utils, if it does, then return 'is not valid client comp'
@@ -136,4 +139,4 @@ function checkReactHooks(node) {
136139

137140
// render component tree using react flow, passing in node and recursvely call on child nodes
138141

139-
module.exports = { grabFile };
142+
module.exports = { Parser };

src/treeTemplates/tree.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const Tree = {
2+
id: undefined,
3+
fileName: undefined,
4+
filePath: undefined,
5+
children: [],
6+
parentList: [],
7+
isClientComponent: false
8+
}
9+
10+
module.exports = { Tree };
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const path = require('path');
1+
const path = require('path')
22

33

44
module.exports = {

0 commit comments

Comments
 (0)