@@ -3,17 +3,30 @@ namespace ts.refactor {
3
3
const refactorName = "Convert export" ;
4
4
const actionNameDefaultToNamed = "Convert default export to named export" ;
5
5
const actionNameNamedToDefault = "Convert named export to default export" ;
6
+
6
7
registerRefactor ( refactorName , {
7
8
getAvailableActions ( context ) : readonly ApplicableRefactorInfo [ ] {
8
9
const info = getInfo ( context , context . triggerReason === "invoked" ) ;
9
10
if ( ! info ) return emptyArray ;
10
- const description = info . wasDefault ? Diagnostics . Convert_default_export_to_named_export . message : Diagnostics . Convert_named_export_to_default_export . message ;
11
- const actionName = info . wasDefault ? actionNameDefaultToNamed : actionNameNamedToDefault ;
12
- return [ { name : refactorName , description, actions : [ { name : actionName , description } ] } ] ;
11
+
12
+ if ( info . error === undefined ) {
13
+ const description = info . info . wasDefault ? Diagnostics . Convert_default_export_to_named_export . message : Diagnostics . Convert_named_export_to_default_export . message ;
14
+ const actionName = info . info . wasDefault ? actionNameDefaultToNamed : actionNameNamedToDefault ;
15
+ return [ { name : refactorName , description, actions : [ { name : actionName , description } ] } ] ;
16
+ }
17
+
18
+ if ( context . preferences . provideRefactorNotApplicableReason ) {
19
+ return [
20
+ { name : refactorName , description : Diagnostics . Convert_default_export_to_named_export . message , actions : [ { name : actionNameDefaultToNamed , description : Diagnostics . Convert_default_export_to_named_export . message , notApplicableReason : info . error } ] } ,
21
+ { name : refactorName , description : Diagnostics . Convert_named_export_to_default_export . message , actions : [ { name : actionNameNamedToDefault , description : Diagnostics . Convert_named_export_to_default_export . message , notApplicableReason : info . error } ] } ,
22
+ ] ;
23
+ }
24
+
25
+ return emptyArray ;
13
26
} ,
14
27
getEditsForAction ( context , actionName ) : RefactorEditInfo {
15
28
Debug . assert ( actionName === actionNameDefaultToNamed || actionName === actionNameNamedToDefault , "Unexpected action name" ) ;
16
- const edits = textChanges . ChangeTracker . with ( context , t => doChange ( context . file , context . program , Debug . checkDefined ( getInfo ( context ) , "context must have info" ) , t , context . cancellationToken ) ) ;
29
+ const edits = textChanges . ChangeTracker . with ( context , t => doChange ( context . file , context . program , Debug . checkDefined ( getInfo ( context ) ?. info , "context must have info" ) , t , context . cancellationToken ) ) ;
17
30
return { edits, renameFilename : undefined , renameLocation : undefined } ;
18
31
} ,
19
32
} ) ;
@@ -27,13 +40,21 @@ namespace ts.refactor {
27
40
readonly exportingModuleSymbol : Symbol ;
28
41
}
29
42
30
- function getInfo ( context : RefactorContext , considerPartialSpans = true ) : Info | undefined {
43
+ type InfoOrError = {
44
+ info : Info ,
45
+ error ?: never
46
+ } | {
47
+ info ?: never ,
48
+ error : string
49
+ } ;
50
+
51
+ function getInfo ( context : RefactorContext , considerPartialSpans = true ) : InfoOrError | undefined {
31
52
const { file } = context ;
32
53
const span = getRefactorContextSpan ( context ) ;
33
54
const token = getTokenAtPosition ( file , span . start ) ;
34
55
const exportNode = ! ! ( token . parent && getSyntacticModifierFlags ( token . parent ) & ModifierFlags . Export ) && considerPartialSpans ? token . parent : getParentNodeInSpan ( token , file , span ) ;
35
56
if ( ! exportNode || ( ! isSourceFile ( exportNode . parent ) && ! ( isModuleBlock ( exportNode . parent ) && isAmbientModule ( exportNode . parent . parent ) ) ) ) {
36
- return undefined ;
57
+ return { error : getLocaleSpecificMessage ( Diagnostics . Could_not_find_export_statement ) } ;
37
58
}
38
59
39
60
const exportingModuleSymbol = isSourceFile ( exportNode . parent ) ? exportNode . parent . symbol : exportNode . parent . parent . symbol ;
@@ -42,7 +63,7 @@ namespace ts.refactor {
42
63
const wasDefault = ! ! ( flags & ModifierFlags . Default ) ;
43
64
// If source file already has a default export, don't offer refactor.
44
65
if ( ! ( flags & ModifierFlags . Export ) || ! wasDefault && exportingModuleSymbol . exports ! . has ( InternalSymbolName . Default ) ) {
45
- return undefined ;
66
+ return { error : getLocaleSpecificMessage ( Diagnostics . This_file_already_has_a_default_export ) } ;
46
67
}
47
68
48
69
switch ( exportNode . kind ) {
@@ -53,7 +74,7 @@ namespace ts.refactor {
53
74
case SyntaxKind . TypeAliasDeclaration :
54
75
case SyntaxKind . ModuleDeclaration : {
55
76
const node = exportNode as FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | EnumDeclaration | TypeAliasDeclaration | NamespaceDeclaration ;
56
- return node . name && isIdentifier ( node . name ) ? { exportNode : node , exportName : node . name , wasDefault, exportingModuleSymbol } : undefined ;
77
+ return node . name && isIdentifier ( node . name ) ? { info : { exportNode : node , exportName : node . name , wasDefault, exportingModuleSymbol } } : undefined ;
57
78
}
58
79
case SyntaxKind . VariableStatement : {
59
80
const vs = exportNode as VariableStatement ;
@@ -64,7 +85,7 @@ namespace ts.refactor {
64
85
const decl = first ( vs . declarationList . declarations ) ;
65
86
if ( ! decl . initializer ) return undefined ;
66
87
Debug . assert ( ! wasDefault , "Can't have a default flag here" ) ;
67
- return isIdentifier ( decl . name ) ? { exportNode : vs , exportName : decl . name , wasDefault, exportingModuleSymbol } : undefined ;
88
+ return isIdentifier ( decl . name ) ? { info : { exportNode : vs , exportName : decl . name , wasDefault, exportingModuleSymbol } } : undefined ;
68
89
}
69
90
default :
70
91
return undefined ;
0 commit comments