1- import { uniq } from 'rambda'
2- import { findChildContainingExactPosition , getChangesTracker , getPositionHighlights , isValidInitializerForDestructure , makeUniqueName } from '../../../utils'
1+ import { uniqBy } from 'lodash'
2+ import { getChangesTracker , getPositionHighlights , isValidInitializerForDestructure } from '../../../utils'
3+ import isVueFileName from '../../../utils/vue/isVueFileName'
4+ import { checkNeedToRefsWrap } from './vueSupportUtils'
5+ import { getDestructureReplaceInfo } from './getDestructureReplaceInfo'
36
47export default ( node : ts . Node , sourceFile : ts . SourceFile , formatOptions : ts . FormatCodeSettings | undefined , languageService : ts . LanguageService ) => {
58 const isValidInitializer = ts . isVariableDeclaration ( node . parent ) && node . parent . initializer && isValidInitializerForDestructure ( node . parent . initializer )
@@ -12,52 +15,32 @@ export default (node: ts.Node, sourceFile: ts.SourceFile, formatOptions: ts.Form
1215 if ( ! highlightPositions ) return
1316 const tracker = getChangesTracker ( formatOptions ?? { } )
1417
15- const propertyNames : Array < { initial : string ; unique : string | undefined } > = [ ]
16- let nodeToReplaceWithBindingPattern : ts . Identifier | undefined
18+ const res = getDestructureReplaceInfo ( highlightPositions , node , sourceFile , languageService )
1719
18- for ( const pos of highlightPositions ) {
19- const highlightedNode = findChildContainingExactPosition ( sourceFile , pos )
20+ if ( ! res ) return
2021
21- if ( ! highlightedNode ) continue
22+ const { propertiesToReplace , nodeToReplaceWithBindingPattern } = res
2223
23- if (
24- ts . isElementAccessExpression ( highlightedNode . parent ) ||
25- ts . isTypeQueryNode ( highlightedNode . parent ) ||
26- ( ts . isCallExpression ( highlightedNode . parent . parent ) && highlightedNode . parent . parent . expression === highlightedNode . parent )
27- )
28- return
29-
30- if ( ts . isIdentifier ( highlightedNode ) && ts . isPropertyAccessExpression ( highlightedNode . parent ) ) {
31- const accessorName = highlightedNode . parent . name . getText ( )
24+ if ( ! nodeToReplaceWithBindingPattern || propertiesToReplace . length === 0 ) return
3225
33- if ( ! accessorName ) continue
26+ const shouldHandleVueReactivityLose =
27+ isVueFileName ( sourceFile . fileName ) &&
28+ ts . isVariableDeclaration ( nodeToReplaceWithBindingPattern . parent ) &&
29+ nodeToReplaceWithBindingPattern . parent . initializer &&
30+ checkNeedToRefsWrap ( nodeToReplaceWithBindingPattern . parent . initializer )
3431
35- const uniqueName = makeUniqueName ( accessorName , node , languageService , sourceFile )
32+ for ( const { initial, range, unique } of propertiesToReplace ) {
33+ const uniqueNameIdentifier = ts . factory . createIdentifier ( unique || initial )
3634
37- propertyNames . push ( { initial : accessorName , unique : uniqueName === accessorName ? undefined : uniqueName } )
38- const range =
39- ts . isPropertyAssignment ( highlightedNode . parent . parent ) && highlightedNode . parent . parent . name . getText ( ) === accessorName
40- ? {
41- pos : highlightedNode . parent . parent . pos + highlightedNode . parent . parent . getLeadingTriviaWidth ( ) ,
42- end : highlightedNode . parent . parent . end ,
43- }
44- : { pos, end : highlightedNode . parent . end }
45-
46- tracker . replaceRangeWithText ( sourceFile , range , uniqueName )
47- continue
48- }
49-
50- if ( ts . isIdentifier ( highlightedNode ) && ( ts . isVariableDeclaration ( highlightedNode . parent ) || ts . isParameter ( highlightedNode . parent ) ) ) {
51- // Already met a target node - abort as we encountered direct use of the potential destructured variable
52- if ( nodeToReplaceWithBindingPattern ) return
53- nodeToReplaceWithBindingPattern = highlightedNode
35+ if ( shouldHandleVueReactivityLose ) {
36+ const propertyAccessExpression = ts . factory . createPropertyAccessExpression ( uniqueNameIdentifier , 'value' )
37+ tracker . replaceRange ( sourceFile , range , propertyAccessExpression )
5438 continue
5539 }
40+ tracker . replaceRange ( sourceFile , range , uniqueNameIdentifier )
5641 }
5742
58- if ( ! nodeToReplaceWithBindingPattern || propertyNames . length === 0 ) return
59-
60- const bindings = uniq ( propertyNames ) . map ( ( { initial, unique } ) => {
43+ const bindings = uniqBy ( propertiesToReplace , 'unique' ) . map ( ( { initial, unique } ) => {
6144 return ts . factory . createBindingElement ( undefined , unique ? initial : undefined , unique ?? initial )
6245 } )
6346
@@ -73,6 +56,22 @@ export default (node: ts.Node, sourceFile: ts.SourceFile, formatOptions: ts.Form
7356 bindingPattern ,
7457 )
7558
59+ if ( shouldHandleVueReactivityLose ) {
60+ // Wrap the `defineProps` with `toRefs`
61+ const toRefs = ts . factory . createIdentifier ( 'toRefs' )
62+ const unwrappedCall = nodeToReplaceWithBindingPattern . parent . initializer
63+ const wrappedWithToRefsCall = ts . factory . createCallExpression ( toRefs , undefined , [ unwrappedCall ] )
64+
65+ tracker . replaceRange (
66+ sourceFile ,
67+ {
68+ pos : unwrappedCall . pos ,
69+ end : unwrappedCall . end ,
70+ } ,
71+ wrappedWithToRefsCall ,
72+ )
73+ }
74+
7675 const changes = tracker . getChanges ( )
7776 if ( ! changes ) return undefined
7877 return {
0 commit comments