@@ -286,6 +286,16 @@ namespace ts.server {
286
286
: deduplicate ( outputs , areEqual ) ;
287
287
}
288
288
289
+ function combineProjectOutputFromEveryProject < T > ( projectService : ProjectService , action : ( project : Project ) => ReadonlyArray < T > , areEqual : ( a : T , b : T ) => boolean ) {
290
+ const outputs : T [ ] = [ ] ;
291
+ projectService . forEachProject ( project => {
292
+ if ( project . isOrphan ( ) || ! project . languageServiceEnabled ) return ;
293
+ const theseOutputs = action ( project ) ;
294
+ outputs . push ( ...theseOutputs . filter ( output => ! outputs . some ( o => areEqual ( o , output ) ) ) ) ;
295
+ } ) ;
296
+ return outputs ;
297
+ }
298
+
289
299
function combineProjectOutputWhileOpeningReferencedProjects < T > (
290
300
projects : Projects ,
291
301
projectService : ProjectService ,
@@ -1749,19 +1759,11 @@ namespace ts.server {
1749
1759
const newPath = toNormalizedPath ( args . newFilePath ) ;
1750
1760
const formatOptions = this . getHostFormatOptions ( ) ;
1751
1761
const preferences = this . getHostPreferences ( ) ;
1752
-
1753
- const changes : ( protocol . FileCodeEdits | FileTextChanges ) [ ] = [ ] ;
1754
- this . projectService . forEachProject ( project => {
1755
- if ( project . isOrphan ( ) || ! project . languageServiceEnabled ) return ;
1756
- for ( const fileTextChanges of project . getLanguageService ( ) . getEditsForFileRename ( oldPath , newPath , formatOptions , preferences ) ) {
1757
- // Subsequent projects may make conflicting edits to the same file -- just go with the first.
1758
- if ( ! changes . some ( f => f . fileName === fileTextChanges . fileName ) ) {
1759
- changes . push ( simplifiedResult ? this . mapTextChangeToCodeEdit ( project , fileTextChanges ) : fileTextChanges ) ;
1760
- }
1761
- }
1762
- } ) ;
1763
-
1764
- return changes as ReadonlyArray < protocol . FileCodeEdits > | ReadonlyArray < FileTextChanges > ;
1762
+ const changes = combineProjectOutputFromEveryProject (
1763
+ this . projectService ,
1764
+ project => project . getLanguageService ( ) . getEditsForFileRename ( oldPath , newPath , formatOptions , preferences ) ,
1765
+ ( a , b ) => a . fileName === b . fileName ) ;
1766
+ return simplifiedResult ? changes . map ( c => this . mapTextChangeToCodeEditUsingScriptInfo ( c ) ) : changes ;
1765
1767
}
1766
1768
1767
1769
private getCodeFixes ( args : protocol . CodeFixRequestArgs , simplifiedResult : boolean ) : ReadonlyArray < protocol . CodeFixAction > | ReadonlyArray < CodeFixAction > | undefined {
@@ -1835,8 +1837,15 @@ namespace ts.server {
1835
1837
}
1836
1838
1837
1839
private mapTextChangeToCodeEdit ( project : Project , change : FileTextChanges ) : protocol . FileCodeEdits {
1838
- const path = normalizedPathToPath ( toNormalizedPath ( change . fileName ) , this . host . getCurrentDirectory ( ) , fileName => this . getCanonicalFileName ( fileName ) ) ;
1839
- return mapTextChangesToCodeEdits ( change , project . getSourceFileOrConfigFile ( path ) ) ;
1840
+ return mapTextChangesToCodeEdits ( change , project . getSourceFileOrConfigFile ( this . normalizePath ( change . fileName ) ) ) ;
1841
+ }
1842
+
1843
+ private mapTextChangeToCodeEditUsingScriptInfo ( change : FileTextChanges ) : protocol . FileCodeEdits {
1844
+ return mapTextChangesToCodeEditsUsingScriptInfo ( change , this . projectService . getScriptInfo ( this . normalizePath ( change . fileName ) ) ) ;
1845
+ }
1846
+
1847
+ private normalizePath ( fileName : string ) {
1848
+ return normalizedPathToPath ( toNormalizedPath ( fileName ) , this . host . getCurrentDirectory ( ) , fileName => this . getCanonicalFileName ( fileName ) ) ;
1840
1849
}
1841
1850
1842
1851
private convertTextChangeToCodeEdit ( change : TextChange , scriptInfo : ScriptInfo ) : protocol . CodeEdit {
@@ -2361,6 +2370,13 @@ namespace ts.server {
2361
2370
}
2362
2371
}
2363
2372
2373
+ function mapTextChangesToCodeEditsUsingScriptInfo ( textChanges : FileTextChanges , scriptInfo : ScriptInfo | undefined ) : protocol . FileCodeEdits {
2374
+ Debug . assert ( ! ! textChanges . isNewFile === ! scriptInfo ) ;
2375
+ return scriptInfo
2376
+ ? { fileName : textChanges . fileName , textChanges : textChanges . textChanges . map ( textChange => convertTextChangeToCodeEditUsingScriptInfo ( textChange , scriptInfo ) ) }
2377
+ : convertNewFileTextChangeToCodeEdit ( textChanges ) ;
2378
+ }
2379
+
2364
2380
function convertTextChangeToCodeEdit ( change : TextChange , sourceFile : SourceFile ) : protocol . CodeEdit {
2365
2381
return {
2366
2382
start : convertToLocation ( sourceFile . getLineAndCharacterOfPosition ( change . span . start ) ) ,
@@ -2369,6 +2385,10 @@ namespace ts.server {
2369
2385
} ;
2370
2386
}
2371
2387
2388
+ function convertTextChangeToCodeEditUsingScriptInfo ( change : TextChange , scriptInfo : ScriptInfo ) {
2389
+ return { start : scriptInfo . positionToLineOffset ( change . span . start ) , end : scriptInfo . positionToLineOffset ( textSpanEnd ( change . span ) ) , newText : change . newText } ;
2390
+ }
2391
+
2372
2392
function convertNewFileTextChangeToCodeEdit ( textChanges : FileTextChanges ) : protocol . FileCodeEdits {
2373
2393
Debug . assert ( textChanges . textChanges . length === 1 ) ;
2374
2394
const change = first ( textChanges . textChanges ) ;
0 commit comments