Skip to content

Commit 29a86de

Browse files
authored
feat: support voca syntax (#168)
1 parent b837ebc commit 29a86de

File tree

5 files changed

+87
-61
lines changed

5 files changed

+87
-61
lines changed

libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts

Lines changed: 68 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -26,69 +26,80 @@ export function extractExportsFromExportDefaultDeclaration(
2626
visitor: ExportVisitor,
2727
filePath: string,
2828
path: NodePath<t.ExportDefaultDeclaration>
29-
): Export {
29+
): Export[] {
3030
let name: string;
3131
let id: string;
3232

33-
switch (path.node.declaration.type) {
34-
case "Identifier": {
35-
name = path.node.declaration.name;
36-
id = visitor._getBindingId(path.get("declaration"));
37-
break;
38-
}
39-
case "NewExpression": {
40-
if (path.node.declaration.callee.type !== "Identifier") {
41-
// unsupported
42-
throw new Error("Unsupported export default declaration");
43-
}
44-
name = path.node.declaration.callee.name;
45-
// idk if this is correct
46-
id = visitor._getNodeId(path.get("declaration"));
33+
const declaration = path.get("declaration");
4734

48-
break;
49-
}
50-
case "FunctionDeclaration":
51-
case "ClassDeclaration": {
52-
name = path.node.declaration.id
53-
? path.node.declaration.id.name
54-
: "default";
55-
id = visitor._getNodeId(path.get("declaration"));
56-
break;
57-
}
58-
case "CallExpression": {
59-
// e.g export default func(...)
60-
name = "default";
61-
id = visitor._getNodeId(path.get("declaration"));
62-
break;
63-
}
64-
case "ObjectExpression": {
65-
// e.g export default {}
66-
name = "default";
67-
id = visitor._getNodeId(path.get("declaration"));
68-
break;
69-
}
70-
default: {
71-
// we could also put anon here, but that would be a bit weird
72-
// name = "anonymous"
35+
if (declaration.isIdentifier()) {
36+
name = declaration.node.name;
37+
id = visitor._getBindingId(declaration);
38+
} else if (declaration.isLiteral()) {
39+
name = "default";
40+
id = visitor._getNodeId(declaration);
41+
} else if (declaration.isNewExpression()) {
42+
if (declaration.node.callee.type !== "Identifier") {
7343
// unsupported
74-
// examples which we don't support:
75-
// export default true
76-
// export default 1
77-
// export default "string"
78-
// export default []
79-
// etc.
80-
throw new Error(
81-
`Unsupported export default declaration at ${visitor._getNodeId(path)}`
82-
);
44+
throw new Error("Unsupported export default declaration");
45+
}
46+
name = declaration.node.callee.name;
47+
// idk if this is correct
48+
id = visitor._getNodeId(declaration);
49+
} else if (
50+
declaration.isFunctionDeclaration() ||
51+
declaration.isClassDeclaration()
52+
) {
53+
name = declaration.node.id ? declaration.node.id.name : "default";
54+
id = visitor._getNodeId(declaration);
55+
} else if (declaration.isCallExpression()) {
56+
name = "default";
57+
id = visitor._getNodeId(declaration);
58+
} else if (declaration.isObjectExpression()) {
59+
const exports: Export[] = [];
60+
for (const property of declaration.get("properties")) {
61+
if (property.isObjectProperty()) {
62+
const key = property.get("key");
63+
const value = property.get("value");
64+
if (!key.isIdentifier()) {
65+
throw new Error("unsupported syntax");
66+
}
67+
exports.push({
68+
id: visitor._getBindingId(value),
69+
filePath,
70+
name: value.isIdentifier() ? value.node.name : key.node.name,
71+
renamedTo: key.node.name,
72+
default: false,
73+
module: false,
74+
});
75+
}
8376
}
77+
78+
return exports;
79+
} else {
80+
// we could also put anon here, but that would be a bit weird
81+
// name = "anonymous"
82+
// unsupported
83+
// examples which we don't support:
84+
// export default true
85+
// export default 1
86+
// export default "string"
87+
// export default {}
88+
// export default []
89+
// etc.
90+
throw new Error(
91+
`Unsupported export default declaration at ${visitor._getNodeId(path)}`
92+
);
8493
}
8594

86-
return {
87-
id: id,
88-
filePath,
89-
name: name,
90-
renamedTo: name,
91-
default: true,
92-
module: false,
93-
};
95+
return [
96+
{
97+
id: id,
98+
filePath,
99+
name: name,
100+
renamedTo: name,
101+
default: true,
102+
module: false,
103+
},
104+
];
94105
}

libraries/analysis-javascript/lib/target/export/ExportVisitor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export class ExportVisitor extends AbstractSyntaxTreeVisitor {
5353
path: NodePath<t.ExportDefaultDeclaration>
5454
) => void = (path) => {
5555
this._exports.push(
56-
extractExportsFromExportDefaultDeclaration(this, this.filePath, path)
56+
...extractExportsFromExportDefaultDeclaration(this, this.filePath, path)
5757
);
5858
};
5959

libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor {
305305
if (path.node.object.type === "ThisExpression") {
306306
const parent = this._getThisParent(path);
307307

308+
if (!parent) {
309+
return;
310+
}
308311
const _object = this.objectTypeMap.get(this._getNodeId(parent));
309312

310313
if (!_object) {

libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ export class RelationVisitor extends AbstractSyntaxTreeVisitor {
244244

245245
const parent = this._getThisParent(path);
246246

247-
this._createRelation(path, type, [parent]);
247+
if (parent) {
248+
this._createRelation(path, type, [parent]);
249+
}
248250
};
249251

250252
public ArrayExpression: (path: NodePath<t.ArrayExpression>) => void = (

libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,16 @@ export class AbstractSyntaxTreeVisitor implements TraverseOptions {
206206
return this._getNodeId(path);
207207
}
208208

209+
if (
210+
path.parentPath.isExportSpecifier() &&
211+
path.parentPath.get("exported") === path
212+
) {
213+
// we are the export name of a renamed export
214+
// so this is the first definition of foo
215+
// e.g. export {bar as foo}
216+
return this._getNodeId(path);
217+
}
218+
209219
if (
210220
(path.parentPath.isObjectProperty() ||
211221
path.parentPath.isObjectMethod()) &&
@@ -290,7 +300,7 @@ export class AbstractSyntaxTreeVisitor implements TraverseOptions {
290300
path
291301
)}`
292302
);
293-
return <NodePath<t.Program>>path.findParent((p) => p.isProgram());
303+
return undefined; // <NodePath<t.Program>>path.findParent((p) => p.isProgram());
294304
} else {
295305
throw new Error(
296306
`ThisExpression without parent function found at ${this._getNodeId(
@@ -311,7 +321,7 @@ export class AbstractSyntaxTreeVisitor implements TraverseOptions {
311321
path
312322
)}`
313323
);
314-
return <NodePath<t.Program>>path.findParent((p) => p.isProgram());
324+
return undefined; // <NodePath<t.Program>>path.findParent((p) => p.isProgram());
315325
} else {
316326
throw new Error(
317327
`ThisExpression without parent function found at ${this._getNodeId(

0 commit comments

Comments
 (0)