Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 207477e

Browse files
feat: autofix in define-props-declaration: runtime syntax to type-based syntax (#2465)
copy type for unknown expressions, ignore fixing cases when error is thrown
1 parent f301546 commit 207477e

File tree

2 files changed

+83
-56
lines changed

2 files changed

+83
-56
lines changed

‎lib/rules/define-props-declaration.js

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ function getComponentPropData(prop, sourceCode) {
4747
throw new Error(`Unexpected prop type: ${prop.type}.`)
4848
}
4949
const type = optionGetType(prop.value, sourceCode)
50-
if (type === null) {
51-
throw new Error(`Unable to read prop type`)
52-
}
5350
const required = optionGetRequired(prop.value)
5451
const defaultValue = optionGetDefault(prop.value)
5552

@@ -64,7 +61,7 @@ function getComponentPropData(prop, sourceCode) {
6461
/**
6562
* @param {Expression} node
6663
* @param {SourceCode} sourceCode
67-
* @returns {string | null}
64+
* @returns {string}
6865
*/
6966
function optionGetType(node, sourceCode) {
7067
switch (node.type) {
@@ -74,7 +71,7 @@ function optionGetType(node, sourceCode) {
7471
case 'ObjectExpression': {
7572
const typeProperty = utils.findProperty(node, 'type')
7673
if (typeProperty == null) {
77-
return null
74+
return sourceCode.getText(node)
7875
}
7976
return optionGetType(typeProperty.value, sourceCode)
8077
}
@@ -83,7 +80,7 @@ function optionGetType(node, sourceCode) {
8380
.map((element) => {
8481
// TODO handle SpreadElement
8582
if (element === null || element.type === 'SpreadElement') {
86-
return null
83+
return sourceCode.getText(node)
8784
}
8885

8986
return optionGetType(element, sourceCode)
@@ -94,7 +91,7 @@ function optionGetType(node, sourceCode) {
9491
case 'TSAsExpression': {
9592
const typeAnnotation = node.typeAnnotation
9693
if (typeAnnotation.typeName.name !== 'PropType') {
97-
return null
94+
return sourceCode.getText(node)
9895
}
9996

10097
// in some project configuration parser populates deprecated field `typeParameters` instead of `typeArguments`
@@ -108,20 +105,15 @@ function optionGetType(node, sourceCode) {
108105
: typeArguments.params[0]
109106

110107
if (typeArgument === undefined) {
111-
return null
108+
return sourceCode.getText(node)
112109
}
113110

114111
return sourceCode.getText(typeArgument)
115112
}
116-
117-
case 'FunctionExpression':
118-
case 'ArrowFunctionExpression': {
119-
return null
113+
default: {
114+
return sourceCode.getText(node)
120115
}
121116
}
122-
123-
// Unknown
124-
return null
125117
}
126118

127119
/**
@@ -215,55 +207,66 @@ module.exports = {
215207
node,
216208
messageId: 'hasArg',
217209
*fix(fixer) {
218-
const propTypes = props.map((prop) =>
219-
getComponentPropData(prop, sourceCode)
220-
)
221-
222-
const definePropsType = `{ ${propTypes
223-
.map(
224-
({ name, type, required, defaultValue }) =>
225-
`${name}${
226-
required === false || defaultValue ? '?' : ''
227-
}: ${type}`
210+
try {
211+
const propTypes = props.map((prop) =>
212+
getComponentPropData(prop, sourceCode)
228213
)
229-
.join(', ')} }`
230214

231-
// remove defineProps function parameters
232-
yield fixer.replaceText(node.arguments[0], '')
215+
const definePropsType = `{ ${propTypes
216+
.map(
217+
({ name, type, required, defaultValue }) =>
218+
`${name}${
219+
required === false || defaultValue ? '?' : ''
220+
}: ${type}`
221+
)
222+
.join(', ')} }`
223+
224+
// remove defineProps function parameters
225+
yield fixer.replaceText(node.arguments[0], '')
233226

234-
// add type annotation
235-
if (separateInterface) {
236-
const variableDeclarationNode = node.parent.parent
237-
if (!variableDeclarationNode) {
238-
return
227+
// add type annotation
228+
if (separateInterface) {
229+
const variableDeclarationNode = node.parent.parent
230+
if (!variableDeclarationNode) {
231+
return
232+
}
233+
234+
yield fixer.insertTextBefore(
235+
variableDeclarationNode,
236+
`interface Props ${definePropsType.replace(
237+
/;/g,
238+
','
239+
)}; `
240+
)
241+
yield fixer.insertTextAfter(node.callee, `<Props>`)
242+
} else {
243+
yield fixer.insertTextAfter(
244+
node.callee,
245+
`<${definePropsType}>`
246+
)
239247
}
240248

241-
yield fixer.insertTextBefore(
242-
variableDeclarationNode,
243-
`interface Props ${definePropsType.replace(/;/g, ',')}; `
244-
)
245-
yield fixer.insertTextAfter(node.callee, `<Props>`)
246-
} else {
247-
yield fixer.insertTextAfter(
248-
node.callee,
249-
`<${definePropsType}>`
249+
// add defaults if needed
250+
const defaults = propTypes.filter(
251+
({ defaultValue }) => defaultValue
250252
)
251-
}
253+
if (defaults.length > 0) {
254+
const defaultsCode = defaults
255+
.map(
256+
({ name, defaultValue }) =>
257+
`${name}: ${sourceCode.getText(defaultValue)}`
258+
)
259+
.join(', ')
252260

253-
// add defaults if needed
254-
const defaults = propTypes.filter(
255-
({ defaultValue }) => defaultValue
256-
)
257-
if (defaults.length > 0) {
258-
const defaultsCode = defaults
259-
.map(
260-
({ name, defaultValue }) =>
261-
`${name}: ${sourceCode.getText(defaultValue)}`
261+
yield fixer.insertTextBefore(node, `withDefaults(`)
262+
yield fixer.insertTextAfter(
263+
node,
264+
`, { ${defaultsCode} })`
262265
)
263-
.join(', ')
264-
265-
yieldfixer.insertTextBefore(node,`withDefaults(`)
266-
yieldfixer.insertTextAfter(node,`, { ${defaultsCode} })`)
266+
}
267+
returnnull
268+
}catch(error){
269+
returnnull
267270
}
268271
}
269272
})

‎tests/lib/rules/define-props-declaration.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,30 @@ tester.run('define-props-declaration', rule, {
588588
}
589589
]
590590
},
591+
// Some unhandled expression type
592+
{
593+
filename: 'test.vue',
594+
code: `
595+
<script setup lang="ts">
596+
const props = defineProps({
597+
kind: {
598+
type: typeof Test
599+
}
600+
})
601+
</script>
602+
`,
603+
output: `
604+
<script setup lang="ts">
605+
const props = defineProps<{ kind: typeof Test }>()
606+
</script>
607+
`,
608+
errors: [
609+
{
610+
message: 'Use type-based declaration instead of runtime declaration.',
611+
line: 3
612+
}
613+
]
614+
},
591615
// runtime
592616
{
593617
filename: 'test.vue',

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /