@@ -2,7 +2,8 @@ import _ from 'lodash'
22import addMissingProperties from './codeFixes/addMissingProperties'
33import { changeSortingOfAutoImport , getIgnoreAutoImportSetting , isAutoImportEntryShouldBeIgnored } from './adjustAutoImports'
44import { GetConfig } from './types'
5- import { findChildContainingPosition , getIndentFromPos , patchMethod } from './utils'
5+ import { findChildContainingPosition , getCancellationToken , getIndentFromPos , patchMethod } from './utils'
6+ import namespaceAutoImports from './namespaceAutoImports'
67
78// codeFixes that I managed to put in files
89const externalCodeFixes = [ addMissingProperties ]
@@ -22,33 +23,61 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
2223 [ Diagnostics . Remove_type_from_import_of_0_from_1 , 1 , 0 ] ,
2324 [ Diagnostics . Remove_type_from_import_declaration_from_0 , 0 ] ,
2425 ]
25- const oldCreateCodeFixAction = tsFull . codefix . createCodeFixAction
26+ const addNamespaceImports = [ ] as ts . CodeFixAction [ ]
27+
2628 let prior : readonly ts . CodeFixAction [ ]
29+ let toUnpatch : ( ( ) => void ) [ ] = [ ]
2730 try {
2831 const { importFixName } = tsFull . codefix
2932 const ignoreAutoImportsSetting = getIgnoreAutoImportSetting ( c )
3033 const sortFn = changeSortingOfAutoImport ( c , ( node as ts . Identifier ) . text )
31- tsFull . codefix . createCodeFixAction = ( fixName , changes , description , fixId , fixAllDescription , command ) => {
32- if ( fixName !== importFixName ) return oldCreateCodeFixAction ( fixName , changes , description , fixId , fixAllDescription , command )
33- const placeholderIndexesInfo = moduleSymbolDescriptionPlaceholders . find ( ( [ diag ] ) => diag === description [ 0 ] )
34- let sorting = '-1'
35- if ( placeholderIndexesInfo ) {
36- const targetModule = description [ placeholderIndexesInfo [ 1 ] + 1 ]
37- const symbolName = placeholderIndexesInfo [ 2 ] !== undefined ? description [ placeholderIndexesInfo [ 2 ] + 1 ] : ( node as ts . Identifier ) . text
38- const toIgnore = isAutoImportEntryShouldBeIgnored ( ignoreAutoImportsSetting , targetModule , symbolName )
39- if ( toIgnore ) {
40- return {
41- fixName : 'IGNORE' ,
42- changes : [ ] ,
43- description : '' ,
34+ const unpatch = patchMethod (
35+ tsFull . codefix ,
36+ 'createCodeFixAction' ,
37+ oldCreateCodeFixAction => ( fixName , changes , description , fixId , fixAllDescription , command ) => {
38+ if ( fixName !== importFixName ) return oldCreateCodeFixAction ( fixName , changes , description , fixId , fixAllDescription , command )
39+ const placeholderIndexesInfo = moduleSymbolDescriptionPlaceholders . find ( ( [ diag ] ) => diag === description [ 0 ] )
40+ let sorting = '-1'
41+ if ( placeholderIndexesInfo ) {
42+ const targetModule = description [ placeholderIndexesInfo [ 1 ] + 1 ]
43+ const symbolName = placeholderIndexesInfo [ 2 ] !== undefined ? description [ placeholderIndexesInfo [ 2 ] + 1 ] : ( node as ts . Identifier ) . text
44+
45+ const toIgnore = isAutoImportEntryShouldBeIgnored ( ignoreAutoImportsSetting , targetModule , symbolName )
46+
47+ const namespaceImportAction =
48+ ! toIgnore && namespaceAutoImports ( c , sourceFile , targetModule , preferences , formatOptions , start , symbolName )
49+
50+ if ( namespaceImportAction ) {
51+ const { textChanges, description } = namespaceImportAction
52+ addNamespaceImports . push ( {
53+ fixName : importFixName ,
54+ fixAllDescription : 'Add all missing imports' ,
55+ fixId : 'fixMissingImport' ,
56+ description,
57+ changes : [
58+ {
59+ fileName,
60+ textChanges,
61+ } ,
62+ ] ,
63+ } )
64+ }
65+ if ( toIgnore /* || namespaceImportAction */ ) {
66+ return {
67+ fixName : 'IGNORE' ,
68+ changes : [ ] ,
69+ description : '' ,
70+ }
4471 }
72+ sorting = sortFn ( targetModule ) . toString ( )
73+ // todo this workaround is weird, sort in another way
4574 }
46- sorting = sortFn ( targetModule ) . toString ( )
47- // todo this workaround is weird, sort in another way
48- }
49- return oldCreateCodeFixAction ( fixName + sorting , changes , description , fixId , fixAllDescription , command )
50- }
75+ return oldCreateCodeFixAction ( fixName + sorting , changes , description , fixId , fixAllDescription , command )
76+ } ,
77+ )
78+ toUnpatch . push ( unpatch )
5179 prior = languageService . getCodeFixesAtPosition ( fileName , start , end , errorCodes , formatOptions , preferences )
80+ prior = [ ...addNamespaceImports , ...prior ]
5281 prior = _ . sortBy ( prior , ( { fixName } ) => {
5382 if ( fixName . startsWith ( importFixName ) ) {
5483 return + fixName . slice ( importFixName . length )
@@ -63,7 +92,7 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
6392 throw err
6493 } )
6594 } finally {
66- tsFull . codefix . createCodeFixAction = oldCreateCodeFixAction
95+ toUnpatch . forEach ( x => x ( ) )
6796 }
6897 // todo remove when 5.0 is released after 3 months
6998 // #region fix builtin codefixes/refactorings
@@ -150,12 +179,8 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
150179 languageServiceHost as any /* cancellationToken */ ,
151180 )
152181 const semanticDiagnostics = languageService . getSemanticDiagnostics ( fileName )
153- const cancellationToken = languageServiceHost . getCompilerHost ?.( ) ?. getCancellationToken ?.( ) ?? {
154- isCancellationRequested : ( ) => false ,
155- throwIfCancellationRequested : ( ) => { } ,
156- }
157182 const context : Record < keyof import ( 'typescript-full' ) . CodeFixContextBase , any > = {
158- cancellationToken,
183+ cancellationToken : getCancellationToken ( languageServiceHost ) ,
159184 formatContext : tsFull . formatting . getFormatContext ( formatOptions , languageServiceHost ) ,
160185 host : languageServiceHost ,
161186 preferences,
@@ -164,6 +189,7 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
164189 }
165190 const errorCodes = getFixAllErrorCodes ( )
166191 const ignoreAutoImportsSetting = getIgnoreAutoImportSetting ( c )
192+ const additionalTextChanges : ts . TextChange [ ] = [ ]
167193 for ( const diagnostic of semanticDiagnostics ) {
168194 if ( ! errorCodes . includes ( diagnostic . code ) ) continue
169195 const toUnpatch : ( ( ) => any ) [ ] = [ ]
@@ -185,6 +211,38 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
185211 } ) ,
186212 ( { fix } ) => sortFn ( fix . moduleSpecifier ) ,
187213 )
214+ const firstFix = fixes [ 0 ]
215+ const namespaceImportAction =
216+ ! ! firstFix &&
217+ namespaceAutoImports (
218+ c ,
219+ sourceFile ,
220+ firstFix . fix . moduleSpecifier ,
221+ preferences ,
222+ formatOptions ,
223+ diagnostic . start ! ,
224+ firstFix . symbolName ,
225+ )
226+ if ( namespaceImportAction ) {
227+ fixes = [ ]
228+ if ( ! namespaceImportAction . namespace ) {
229+ additionalTextChanges . push ( ...namespaceImportAction . textChanges )
230+ } else {
231+ const { namespace, useDefaultImport, textChanges } = namespaceImportAction
232+ additionalTextChanges . push ( textChanges [ 1 ] ! )
233+ fixes . unshift ( {
234+ ...fixes [ 0 ] ! ,
235+ fix : {
236+ kind : ImportFixKind . AddNew ,
237+ moduleSpecifier : firstFix . fix . moduleSpecifier ,
238+ importKind : useDefaultImport ? tsFull . ImportKind . Default : tsFull . ImportKind . Namespace ,
239+ addAsTypeOnly : false ,
240+ useRequire : false ,
241+ } ,
242+ symbolName : namespace ,
243+ } as FixInfo )
244+ }
245+ }
188246 if ( ! fixes [ 0 ] ) throw new Error ( 'No fixes' )
189247 return fixes [ 0 ]
190248 } ) as any ,
@@ -209,7 +267,10 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
209267 }
210268 }
211269 }
212- return tsFull . codefix . createCombinedCodeActions ( tsFull . textChanges . ChangeTracker . with ( context , importAdder . writeFixes ) )
270+ return tsFull . codefix . createCombinedCodeActions ( [
271+ ...tsFull . textChanges . ChangeTracker . with ( context , importAdder . writeFixes ) ,
272+ { fileName, textChanges : additionalTextChanges } ,
273+ ] )
213274 }
214275 return languageService . getCombinedCodeFix ( scope , fixId , formatOptions , preferences )
215276 }
0 commit comments