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'
3
6
4
7
export default ( node : ts . Node , sourceFile : ts . SourceFile , formatOptions : ts . FormatCodeSettings | undefined , languageService : ts . LanguageService ) => {
5
8
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
12
15
if ( ! highlightPositions ) return
13
16
const tracker = getChangesTracker ( formatOptions ?? { } )
14
17
15
- const propertyNames : Array < { initial : string ; unique : string | undefined } > = [ ]
16
- let nodeToReplaceWithBindingPattern : ts . Identifier | undefined
18
+ const res = getDestructureReplaceInfo ( highlightPositions , node , sourceFile , languageService )
17
19
18
- for ( const pos of highlightPositions ) {
19
- const highlightedNode = findChildContainingExactPosition ( sourceFile , pos )
20
+ if ( ! res ) return
20
21
21
- if ( ! highlightedNode ) continue
22
+ const { propertiesToReplace , nodeToReplaceWithBindingPattern } = res
22
23
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
32
25
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 )
34
31
35
- const uniqueName = makeUniqueName ( accessorName , node , languageService , sourceFile )
32
+ for ( const { initial, range, unique } of propertiesToReplace ) {
33
+ const uniqueNameIdentifier = ts . factory . createIdentifier ( unique || initial )
36
34
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 )
54
38
continue
55
39
}
40
+ tracker . replaceRange ( sourceFile , range , uniqueNameIdentifier )
56
41
}
57
42
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 } ) => {
61
44
return ts . factory . createBindingElement ( undefined , unique ? initial : undefined , unique ?? initial )
62
45
} )
63
46
@@ -73,6 +56,22 @@ export default (node: ts.Node, sourceFile: ts.SourceFile, formatOptions: ts.Form
73
56
bindingPattern ,
74
57
)
75
58
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
+
76
75
const changes = tracker . getChanges ( )
77
76
if ( ! changes ) return undefined
78
77
return {
0 commit comments