Skip to content
Open
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4844612
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
b770232
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
99e2f3e
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
f0294e8
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
5a4a15e
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
583c0db
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
4499597
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
17ac982
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
5e1d3b1
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 27, 2024
bc506f9
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 28, 2024
f301546
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 28, 2024
207477e
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 28, 2024
d08bed1
feat: autofix in `define-props-declaration`: runtime syntax to type-b…
mpiniarski May 28, 2024
6cb7153
Update lib/rules/define-props-declaration.js
mpiniarski Jun 21, 2024
f6c205f
fix: required default value = false
mpiniarski Jun 21, 2024
536c6a1
feature: rename autoFixToSeparateInterface option and describe it in …
mpiniarski Jun 21, 2024
100065d
chore: extract fixTypeBased function
mpiniarski Jun 21, 2024
7d9e731
chore: refactor fixTypeBased function
mpiniarski Jun 21, 2024
0715943
chore: refactor componentPropsTypeCode creation
mpiniarski Jun 24, 2024
bbdc134
fix: fix tests failing
mpiniarski Jul 1, 2024
2a1c654
feature: remove autoFixToSeparateInterface option
mpiniarski Jul 1, 2024
7cdf3ff
Merge branch 'master' into feature/#2465_autofix_in_define-props-decl…
mpiniarski Jul 2, 2024
0e6ea56
Fix tests
FloEdelmann Jul 2, 2024
e9d4400
feature: code cleanup
mpiniarski Jul 3, 2024
0bd915b
Lint
FloEdelmann Jul 4, 2024
1d58a2b
feature: handle array as props list (#2465)
mpiniarski Jul 15, 2024
da17d74
feature: catch errors and ignore them (#2465)
mpiniarski Jul 26, 2024
6634c2d
feature: do not handle array prop declaration (#2465)
mpiniarski Jul 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: autofix in define-props-declaration: runtime syntax to type-b…
…ased syntax (#2465)

copy type for unknown expressions, ignore fixing cases when error is thrown
  • Loading branch information
mpiniarski committed May 28, 2024
commit 207477eb4953d929fbb9db15a320feda2577abe6
115 changes: 59 additions & 56 deletions lib/rules/define-props-declaration.js
Original file line number Diff line number Diff line change
@@ -47,9 +47,6 @@ function getComponentPropData(prop, sourceCode) {
throw new Error(`Unexpected prop type: ${prop.type}.`)
}
const type = optionGetType(prop.value, sourceCode)
if (type === null) {
throw new Error(`Unable to read prop type`)
}
const required = optionGetRequired(prop.value)
const defaultValue = optionGetDefault(prop.value)

@@ -64,7 +61,7 @@ function getComponentPropData(prop, sourceCode) {
/**
* @param {Expression} node
* @param {SourceCode} sourceCode
* @returns {string | null}
* @returns {string}
*/
function optionGetType(node, sourceCode) {
switch (node.type) {
@@ -74,7 +71,7 @@ function optionGetType(node, sourceCode) {
case 'ObjectExpression': {
const typeProperty = utils.findProperty(node, 'type')
if (typeProperty == null) {
return null
return sourceCode.getText(node)
}
return optionGetType(typeProperty.value, sourceCode)
}
@@ -83,7 +80,7 @@ function optionGetType(node, sourceCode) {
.map((element) => {
// TODO handle SpreadElement
if (element === null || element.type === 'SpreadElement') {
return null
return sourceCode.getText(node)
}

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

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

if (typeArgument === undefined) {
return null
return sourceCode.getText(node)
}

return sourceCode.getText(typeArgument)
}

case 'FunctionExpression':
case 'ArrowFunctionExpression': {
return null
default: {
return sourceCode.getText(node)
}
}

// Unknown
return null
}

/**
@@ -215,55 +207,66 @@ module.exports = {
node,
messageId: 'hasArg',
*fix(fixer) {
const propTypes = props.map((prop) =>
getComponentPropData(prop, sourceCode)
)

const definePropsType = `{ ${propTypes
.map(
({ name, type, required, defaultValue }) =>
`${name}${
required === false || defaultValue ? '?' : ''
}: ${type}`
try {
const propTypes = props.map((prop) =>
getComponentPropData(prop, sourceCode)
)
.join(', ')} }`

// remove defineProps function parameters
yield fixer.replaceText(node.arguments[0], '')
const definePropsType = `{ ${propTypes
.map(
({ name, type, required, defaultValue }) =>
`${name}${
required === false || defaultValue ? '?' : ''
}: ${type}`
)
.join(', ')} }`

// remove defineProps function parameters
yield fixer.replaceText(node.arguments[0], '')

// add type annotation
if (separateInterface) {
const variableDeclarationNode = node.parent.parent
if (!variableDeclarationNode) {
return
// add type annotation
if (separateInterface) {
const variableDeclarationNode = node.parent.parent
if (!variableDeclarationNode) {
return
}

yield fixer.insertTextBefore(
variableDeclarationNode,
`interface Props ${definePropsType.replace(
/;/g,
','
)}; `
)
yield fixer.insertTextAfter(node.callee, `<Props>`)
} else {
yield fixer.insertTextAfter(
node.callee,
`<${definePropsType}>`
)
}

yield fixer.insertTextBefore(
variableDeclarationNode,
`interface Props ${definePropsType.replace(/;/g, ',')}; `
)
yield fixer.insertTextAfter(node.callee, `<Props>`)
} else {
yield fixer.insertTextAfter(
node.callee,
`<${definePropsType}>`
// add defaults if needed
const defaults = propTypes.filter(
({ defaultValue }) => defaultValue
)
}
if (defaults.length > 0) {
const defaultsCode = defaults
.map(
({ name, defaultValue }) =>
`${name}: ${sourceCode.getText(defaultValue)}`
)
.join(', ')

// add defaults if needed
const defaults = propTypes.filter(
({ defaultValue }) => defaultValue
)
if (defaults.length > 0) {
const defaultsCode = defaults
.map(
({ name, defaultValue }) =>
`${name}: ${sourceCode.getText(defaultValue)}`
yield fixer.insertTextBefore(node, `withDefaults(`)
yield fixer.insertTextAfter(
node,
`, { ${defaultsCode} })`
)
.join(', ')

yield fixer.insertTextBefore(node, `withDefaults(`)
yield fixer.insertTextAfter(node, `, { ${defaultsCode} })`)
}
return null
} catch (error) {
return null
}
}
})
24 changes: 24 additions & 0 deletions tests/lib/rules/define-props-declaration.js
Original file line number Diff line number Diff line change
@@ -588,6 +588,30 @@ tester.run('define-props-declaration', rule, {
}
]
},
// Some unhandled expression type
{
filename: 'test.vue',
code: `
<script setup lang="ts">
const props = defineProps({
kind: {
type: typeof Test
}
})
</script>
`,
output: `
<script setup lang="ts">
const props = defineProps<{ kind: typeof Test }>()
</script>
`,
errors: [
{
message: 'Use type-based declaration instead of runtime declaration.',
line: 3
}
]
},
// runtime
{
filename: 'test.vue',