Skip to content

Commit ed5d9bd

Browse files
feat: add manual list (#76)
1 parent 8fe2fbc commit ed5d9bd

15 files changed

+1093
-802
lines changed

bin/vue-codemod.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ async function main() {
9393

9494
// init global params
9595
global.globalApi = []
96+
global.manualList = []
97+
global.scriptLine = 0
9698
global.outputReport = {}
9799

98100
const resolvedPaths = globby.sync(files as string[])

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,12 @@
3636
"globby": "^11.0.2",
3737
"jscodeshift": "^0.11.0",
3838
"lru-cache": "^6.0.0",
39+
"prettier": "^2.3.1",
3940
"readline-sync": "^1.4.10",
4041
"source-map": "^0.6.1",
42+
"table": "^6.7.1",
4143
"vue-eslint-parser": "^7.6.0",
42-
"yargs": "^16.2.0",
43-
"prettier": "^2.3.1"
44+
"yargs": "^16.2.0"
4445
},
4546
"devDependencies": {
4647
"@types/debug": "^4.1.5",

src/global.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,19 @@ export type GlobalApi = {
44
path: string
55
}
66

7+
export type ManualList = {
8+
path: string
9+
position: string
10+
name: string
11+
suggest: string
12+
website: string
13+
}
14+
715
declare global {
816
// Use to add global variables used by components to main.js
917
var globalApi: GlobalApi[]
18+
var manualList: ManualList[]
19+
var scriptLine: number
1020
var outputReport: { [key: string]: number }
1121
var subRules: { [key: string]: number }
1222
}

src/report.ts

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,51 @@
11
import * as fs from 'fs'
2+
import { table } from 'table'
3+
4+
export function pushManualList(
5+
path: string,
6+
node: any,
7+
name: string,
8+
suggest: string,
9+
website: string
10+
) {
11+
let index = 0
12+
const filepath = path.split('.')
13+
if (filepath[filepath.length - 1] === 'vue') {
14+
index = global.scriptLine - 1
15+
} else {
16+
index = 0
17+
}
18+
index = node?.value.loc?.start.line + index
19+
let position: string = '[' + index + ',' + node?.value.loc?.start.column + ']'
20+
21+
const list = {
22+
path: path,
23+
position: position,
24+
name: name,
25+
suggest: suggest,
26+
website: website
27+
}
28+
global.manualList.push(list)
29+
}
30+
31+
export function VuePushManualList(
32+
path: string,
33+
node: any,
34+
name: string,
35+
suggest: string,
36+
website: string
37+
) {
38+
let position: string =
39+
'[' + node?.loc?.start.line + ',' + node?.loc?.start.column + ']'
40+
const list = {
41+
path: path,
42+
position: position,
43+
name: name,
44+
suggest: suggest,
45+
website: website
46+
}
47+
global.manualList.push(list)
48+
}
249

350
export function getCntFunc(key: string, outputObj: { [key: string]: number }) {
451
if (!outputObj) {
@@ -7,9 +54,11 @@ export function getCntFunc(key: string, outputObj: { [key: string]: number }) {
754
if (!outputObj.hasOwnProperty(key)) {
855
outputObj[key] = 0
956
}
57+
1058
function cntFunc(quantity: number = 1) {
1159
outputObj[key] += quantity
1260
}
61+
1362
return cntFunc
1463
}
1564

@@ -20,9 +69,11 @@ export function formatterOutput(processFilePath: string[], formatter: string) {
2069
(sum, key) => sum + global.outputReport[key],
2170
0
2271
)
23-
const totalDetected = totalChanged
72+
const totalDetected = totalChanged + global.manualList.length
2473
const transRate =
25-
totalDetected == totalChanged ? 100 : (100 * totalChanged) / totalDetected
74+
totalDetected == totalChanged
75+
? 100
76+
: ((100 * totalChanged) / totalDetected).toFixed(2)
2677

2778
console.log(`--------------------------------------------------`)
2879
console.log(`Processed file:\n${processFilePathList}`)
@@ -54,9 +105,21 @@ export function formatterOutput(processFilePath: string[], formatter: string) {
54105
console.log(global.outputReport)
55106
}
56107

108+
let tableStr: string
109+
let tableOutput: any[][] = [['Rule Names', 'Count']]
110+
for (let i in global.outputReport) {
111+
tableOutput.push([i, global.outputReport[i]])
112+
}
113+
tableStr = table(tableOutput, {
114+
drawHorizontalLine: (lineIndex, rowCount) => {
115+
return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount
116+
},
117+
columns: [{ alignment: 'left' }, { alignment: 'center' }]
118+
})
119+
57120
if (formatter === 'table') {
58121
console.log('The transformation stats: \n')
59-
console.table(global.outputReport)
122+
console.log(tableStr)
60123
}
61124

62125
if (formatter === 'log') {
@@ -65,17 +128,26 @@ export function formatterOutput(processFilePath: string[], formatter: string) {
65128
processFilePath,
66129
totalDetected,
67130
totalChanged,
68-
transRate
131+
transRate,
132+
tableStr
69133
)
70134
}
135+
136+
console.log('The list that you need to migrate your codes mannually')
137+
let index = 1
138+
global.manualList.forEach(manual => {
139+
console.log('index:', index++)
140+
console.log(manual)
141+
})
71142
}
72143

73144
export function logOutput(
74145
processFilePathList: string,
75146
processFilePath: string[],
76147
totalDetected: number,
77148
totalChanged: number,
78-
transRate: number
149+
transRate: string | number,
150+
tableStr: string
79151
) {
80152
let options = {
81153
flags: 'w', //
@@ -92,5 +164,12 @@ export function logOutput(
92164
logger.log(`${totalDetected} places`, `need to be transformed`)
93165
logger.log(`${totalChanged} places`, `was transformed`)
94166
logger.log(`The transformation rate is ${transRate}%`)
95-
logger.log('The transformation stats: \n', global.outputReport)
167+
logger.log('The transformation stats: \n')
168+
logger.log(tableStr)
169+
logger.log('The list that you need to migrate your codes mannually')
170+
let index = 1
171+
global.manualList.forEach(manual => {
172+
logger.log('index:', index++)
173+
logger.log(manual)
174+
})
96175
}

src/runTransformation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ export default function runTransformation(
113113
return source
114114
}
115115

116+
global.scriptLine = descriptor.script.loc.start.line
117+
116118
lang = descriptor.script.lang || 'js'
117119
fileInfo.source = descriptor.script.content
118120
}

transformations/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,15 @@ const transformationMap: {
4040
'remove-extraneous-import': require('./remove-extraneous-import'),
4141

4242
'router4-onready-to-isready': require('./router/router4-onready-to-isready'),
43-
'router-update-addRoute': require('./router/router-update-addRoute')
43+
'router-update-addRoute': require('./router/router-update-addRoute'),
44+
45+
// manual (must be used at the end of list)
46+
'manual-remove-Vue': require('./manual/manual-remove-Vue'),
47+
'manual-remove-VueRouter': require('./manual/manual-remove-VueRouter'),
48+
'manual-remove-on-off-once': require('./manual/manual-remove-on-off-once'),
49+
'manual-remove-router-star': require('./manual/manual-remove-router-star'),
50+
'manual-remove-config-keycodes': require('./manual/manual-remove-config-keycodes'),
51+
'manual-remove-filter': require('./manual/manual-remove-filter')
4452
}
4553

4654
export const excludedTransformations = [
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import wrap from '../../src/wrapAstTransformation'
2+
import type { ASTTransformation } from '../../src/wrapAstTransformation'
3+
import { pushManualList } from '../../src/report'
4+
5+
export const transformAST: ASTTransformation = context => {
6+
const { root, j, filename } = context
7+
8+
const rootNodes: any = root
9+
.find(j.MemberExpression, {
10+
object: {
11+
name: 'Vue'
12+
}
13+
})
14+
.filter((node: any) => node?.value.property?.name !== 'createApp')
15+
if (rootNodes) {
16+
rootNodes.forEach((node: any) => {
17+
const path = filename
18+
const name = 'remove Vue(global api)'
19+
const suggest =
20+
"The rule of thumb is any APIs that globally mutate Vue's behavior are now moved to the app instance. "
21+
const website =
22+
'https://v3.vuejs.org/guide/migration/global-api.html#a-new-global-api-createapp'
23+
pushManualList(path, node, name, suggest, website)
24+
})
25+
}
26+
}
27+
28+
export default wrap(transformAST)
29+
export const parser = 'babylon'
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import wrap from '../../src/wrapAstTransformation'
2+
import type { ASTTransformation } from '../../src/wrapAstTransformation'
3+
import { pushManualList } from '../../src/report'
4+
5+
export const transformAST: ASTTransformation = context => {
6+
const { root, j, filename } = context
7+
8+
const rootNodes: any = root.find(j.Identifier, {
9+
name: 'VueRouter'
10+
})
11+
if (rootNodes) {
12+
rootNodes.forEach((node: any) => {
13+
const path = filename
14+
const name = 'remove VueRouter'
15+
const suggest =
16+
"The rule of thumb is any APIs that globally mutate VueRouter's behavior are now moved to the app instance. "
17+
const website =
18+
'https://next.router.vuejs.org/guide/migration/index.html#moved-the-base-option'
19+
pushManualList(path, node, name, suggest, website)
20+
})
21+
}
22+
}
23+
24+
export default wrap(transformAST)
25+
export const parser = 'babylon'
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import wrap from '../../src/wrapAstTransformation'
2+
import type { ASTTransformation } from '../../src/wrapAstTransformation'
3+
import { pushManualList } from '../../src/report'
4+
5+
export const transformAST: ASTTransformation = context => {
6+
const { root, j, filename } = context
7+
8+
const rootNodes: any = root.find(j.MemberExpression, {
9+
object: {
10+
object: {
11+
name: 'Vue'
12+
},
13+
property: {
14+
name: 'config'
15+
}
16+
},
17+
property: {
18+
name: 'KeyCodes'
19+
}
20+
})
21+
if (rootNodes) {
22+
rootNodes.forEach((node: any) => {
23+
const path = filename
24+
const name = 'remove keycodes'
25+
const suggest = 'config.keyCodes is no longer supported '
26+
const website =
27+
'https://v3.vuejs.org/guide/migration/keycode-modifiers.html'
28+
pushManualList(path, node, name, suggest, website)
29+
})
30+
}
31+
}
32+
33+
export default wrap(transformAST)
34+
export const parser = 'babylon'
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import wrap from '../../src/wrapAstTransformation'
2+
import type { ASTTransformation } from '../../src/wrapAstTransformation'
3+
import { pushManualList } from '../../src/report'
4+
5+
export const transformAST: ASTTransformation = context => {
6+
const { root, j, filename } = context
7+
8+
const rootNodes: any = root
9+
.find(j.Identifier, {
10+
name: 'filters'
11+
})
12+
.filter((node: any) => node?.value.property?.name !== 'createApp')
13+
if (rootNodes) {
14+
rootNodes.forEach((node: any) => {
15+
const path = filename
16+
const name = 'remove filters'
17+
const suggest =
18+
'Filters are removed from Vue 3.0 and no longer supported. '
19+
const website =
20+
'https://v3.vuejs.org/guide/migration/filters.html#overview'
21+
pushManualList(path, node, name, suggest, website)
22+
})
23+
}
24+
25+
const rootNodes2: any = root.find(j.MemberExpression, {
26+
object: {
27+
name: 'Vue'
28+
},
29+
property: {
30+
name: 'filter'
31+
}
32+
})
33+
if (rootNodes2) {
34+
rootNodes2.forEach((node: any) => {
35+
const path = filename
36+
const name = 'remove global filters'
37+
const suggest =
38+
'Instead, you can make your global filters available to all components through globalProperties: '
39+
const website =
40+
'https://v3.vuejs.org/guide/migration/filters.html#global-filters'
41+
pushManualList(path, node, name, suggest, website)
42+
})
43+
}
44+
}
45+
46+
export default wrap(transformAST)
47+
export const parser = 'babylon'

0 commit comments

Comments
 (0)