Skip to content
This repository was archived by the owner on Mar 8, 2019. It is now read-only.

Commit 325d745

Browse files
authored
feat: add variable resolution to components (#75)
* add variable resolution to components * add es5 export support
1 parent a136615 commit 325d745

File tree

2 files changed

+87
-5
lines changed

2 files changed

+87
-5
lines changed

src/utils/__tests__/resolveExportedComponent.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,24 @@ describe('resolveExportedComponent', () => {
2727
expect(resolveExportedComponent(ast).length).toBe(1)
2828
})
2929

30-
it('should return exportedclass style components', () => {
30+
it('should return indirectly exported components', () => {
31+
const ast = babylon().parse(['const test = {}', 'export default test'].join('\n'))
32+
expect(resolveExportedComponent(ast).length).toBe(1)
33+
})
34+
35+
it('should return indirectly exported class style components', () => {
36+
const ast = babylon().parse(
37+
['@Component()', 'class testClass extends Vue{}', 'export default testClass'].join('\n'),
38+
)
39+
expect(resolveExportedComponent(ast).length).toBe(1)
40+
})
41+
42+
it('should return indirectly exported components es5', () => {
43+
const ast = babylon().parse(['const test = {}', 'module.exports = test'].join('\n'))
44+
expect(resolveExportedComponent(ast).length).toBe(1)
45+
})
46+
47+
it('should return exported class style components', () => {
3148
const ast = babylon().parse(
3249
['@Component()', 'export default class Bart extends testComponent {}'].join('\n'),
3350
)

src/utils/resolveExportedComponent.ts

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import resolveExportDeclaration from './resolveExportDeclaration'
66
// tslint:disable-next-line:no-var-requires
77
import recast = require('recast')
88

9+
function ignore(): boolean {
10+
return false
11+
}
12+
913
function isComponentDefinition(path: NodePath): boolean {
1014
return (
1115
// export default {}
@@ -54,8 +58,9 @@ export default function resolveExportedComponent(ast: bt.File): NodePath[] {
5458
// in extenso export default or export myvar
5559
function exportDeclaration(path: NodePath) {
5660
const definitions = resolveExportDeclaration(path).reduce((acc: NodePath[], definition) => {
57-
if (isComponentDefinition(definition)) {
58-
acc.push(definition)
61+
const realDef = resolveIdentifier(ast, definition)
62+
if (realDef && isComponentDefinition(realDef)) {
63+
acc.push(realDef)
5964
}
6065
return acc
6166
}, [])
@@ -67,6 +72,20 @@ export default function resolveExportedComponent(ast: bt.File): NodePath[] {
6772
}
6873

6974
recast.visit(ast.program, {
75+
// to look only at the root we ignore all traversing
76+
visitFunctionDeclaration: ignore,
77+
visitFunctionExpression: ignore,
78+
visitClassDeclaration: ignore,
79+
visitClassExpression: ignore,
80+
visitIfStatement: ignore,
81+
visitWithStatement: ignore,
82+
visitSwitchStatement: ignore,
83+
visitCatchCause: ignore,
84+
visitWhileStatement: ignore,
85+
visitDoWhileStatement: ignore,
86+
visitForStatement: ignore,
87+
visitForInStatement: ignore,
88+
7089
visitDeclareExportDeclaration: exportDeclaration,
7190
visitExportNamedDeclaration: exportDeclaration,
7291
visitExportDefaultDeclaration: exportDeclaration,
@@ -83,11 +102,12 @@ export default function resolveExportedComponent(ast: bt.File): NodePath[] {
83102
// Resolve the value of the right hand side. It should resolve to a call
84103
// expression, something like Vue.extend({})
85104
const pathRight = path.get('right')
86-
if (!isComponentDefinition(pathRight)) {
105+
const realComp = resolveIdentifier(ast, pathRight)
106+
if (!realComp || !isComponentDefinition(realComp)) {
87107
return false
88108
}
89109

90-
setComponent(pathRight)
110+
setComponent(realComp)
91111
return false
92112
},
93113
})
@@ -105,3 +125,48 @@ function normalizeComponentPath(path: NodePath): NodePath {
105125
}
106126
return path
107127
}
128+
129+
function resolveIdentifier(ast: bt.File, path: NodePath): NodePath | null {
130+
if (!bt.isIdentifier(path.node)) {
131+
return path
132+
}
133+
134+
const varName = path.node.name
135+
let comp: NodePath | null = null
136+
137+
recast.visit(ast.program, {
138+
// to look only at the root we ignore all traversing
139+
visitFunctionDeclaration: ignore,
140+
visitFunctionExpression: ignore,
141+
visitClassExpression: ignore,
142+
visitIfStatement: ignore,
143+
visitWithStatement: ignore,
144+
visitSwitchStatement: ignore,
145+
visitCatchCause: ignore,
146+
visitWhileStatement: ignore,
147+
visitDoWhileStatement: ignore,
148+
visitForStatement: ignore,
149+
visitForInStatement: ignore,
150+
151+
visitVariableDeclaration(variablePath: NodePath<bt.VariableDeclaration>) {
152+
const varID = variablePath.node.declarations[0].id
153+
if (!varID || !bt.isIdentifier(varID) || varID.name !== varName) {
154+
return false
155+
}
156+
157+
comp = variablePath.get('declarations', 0).get('init')
158+
return false
159+
},
160+
161+
visitClassDeclaration(classPath: NodePath<bt.ClassDeclaration>) {
162+
const classID = classPath.node.id
163+
if (!classID || !bt.isIdentifier(classID) || classID.name !== varName) {
164+
return false
165+
}
166+
167+
comp = classPath
168+
return false
169+
},
170+
})
171+
return comp
172+
}

0 commit comments

Comments
 (0)