-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathparse-ts.js
90 lines (81 loc) · 2.7 KB
/
parse-ts.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
let ts
try {
ts = require('typescript')
} catch (e) {
// console.error(e)
}
function parseComponentsDeps (scriptContent) {
if (ts === null) {
throw new Error('Please run `npm install -S typescript` to install TypeScript.')
}
const sourceFile = ts.createSourceFile('test', scriptContent, ts.ScriptTarget.ESNext, /* setParentNodes */ true)
return delint(sourceFile)
}
function delint (sourceFile) {
const compNames = {}
const importsMap = {}
delintNode(sourceFile)
function parseDecorator (node) {
// 只处理 @Component({components:{aaa}})
if (node.expression.expression && node.expression.expression.escapedText === 'Component') {
const compArgs = node.expression.arguments
if (compArgs && compArgs.length === 1) {
let vueClassArg = compArgs[0]
if (vueClassArg.kind === ts.SyntaxKind.AsExpression) { // @Component({ components: ...,} as any)
vueClassArg = vueClassArg.expression
}
if (vueClassArg.properties) {
vueClassArg.properties.forEach((classProp) => {
// 处理components属性
if (classProp.name.escapedText === 'components') {
classProp.initializer.properties.forEach((comp) => {
let compName
switch (comp.kind) {
case ts.SyntaxKind.ShorthandPropertyAssignment: // {Comp}
compName = comp.name.escapedText
// report(comp, '1')
break
case ts.SyntaxKind.PropertyAssignment: // {a:Comp}
compName = comp.initializer.escapedText
// report(comp, '2')
break
}
compNames[compName] = true
})
}
})
}
}
}
}
function delintNode (node) {
switch (node.kind) {
case ts.SyntaxKind.ImportDeclaration:
// 只处理 import Comp from 'xxx.vue'
if (node.importClause && node.importClause.name) {
importsMap[node.importClause.name.escapedText] = node.moduleSpecifier.text
}
// report(node, 'import')
break
case ts.SyntaxKind.Decorator:
parseDecorator(node)
break
}
ts.forEachChild(node, delintNode)
}
function report(node, message) { // eslint-disable-line
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart())
console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`)
}
const components = {}
for (const k in compNames) {
if (importsMap.hasOwnProperty(k)) {
components[k] = importsMap[k]
}
}
return {
importsMap,
components
}
}
module.exports = { parseComponentsDeps }