@@ -2950,9 +2950,7 @@ Actual: ${stringify(fullActual)}`);
29502950 }
29512951
29522952 public verifyApplicableRefactorAvailableAtMarker ( negative : boolean , markerName : string ) {
2953- const marker = this . getMarkerByName ( markerName ) ;
2954- const applicableRefactors = this . languageService . getApplicableRefactors ( this . activeFile . fileName , marker . position , ts . defaultPreferences ) ;
2955- const isAvailable = applicableRefactors && applicableRefactors . length > 0 ;
2953+ const isAvailable = this . getApplicableRefactors ( this . getMarkerByName ( markerName ) . position ) . length > 0 ;
29562954 if ( negative && isAvailable ) {
29572955 this . raiseError ( `verifyApplicableRefactorAvailableAtMarker failed - expected no refactor at marker ${ markerName } but found some.` ) ;
29582956 }
@@ -2969,9 +2967,7 @@ Actual: ${stringify(fullActual)}`);
29692967 }
29702968
29712969 public verifyRefactorAvailable ( negative : boolean , name : string , actionName ?: string ) {
2972- const selection = this . getSelection ( ) ;
2973-
2974- let refactors = this . languageService . getApplicableRefactors ( this . activeFile . fileName , selection , ts . defaultPreferences ) || [ ] ;
2970+ let refactors = this . getApplicableRefactors ( this . getSelection ( ) ) ;
29752971 refactors = refactors . filter ( r => r . name === name && ( actionName === undefined || r . actions . some ( a => a . name === actionName ) ) ) ;
29762972 const isAvailable = refactors . length > 0 ;
29772973
@@ -2991,10 +2987,7 @@ Actual: ${stringify(fullActual)}`);
29912987 }
29922988
29932989 public verifyRefactor ( { name, actionName, refactors } : FourSlashInterface . VerifyRefactorOptions ) {
2994- const selection = this . getSelection ( ) ;
2995-
2996- const actualRefactors = ( this . languageService . getApplicableRefactors ( this . activeFile . fileName , selection , ts . defaultPreferences ) || ts . emptyArray )
2997- . filter ( r => r . name === name && r . actions . some ( a => a . name === actionName ) ) ;
2990+ const actualRefactors = this . getApplicableRefactors ( this . getSelection ( ) ) . filter ( r => r . name === name && r . actions . some ( a => a . name === actionName ) ) ;
29982991 this . assertObjectsEqual ( actualRefactors , refactors ) ;
29992992 }
30002993
@@ -3004,8 +2997,7 @@ Actual: ${stringify(fullActual)}`);
30042997 throw new Error ( "Exactly one refactor range is allowed per test." ) ;
30052998 }
30062999
3007- const applicableRefactors = this . languageService . getApplicableRefactors ( this . activeFile . fileName , ts . first ( ranges ) , ts . defaultPreferences ) ;
3008- const isAvailable = applicableRefactors && applicableRefactors . length > 0 ;
3000+ const isAvailable = this . getApplicableRefactors ( ts . first ( ranges ) ) . length > 0 ;
30093001 if ( negative && isAvailable ) {
30103002 this . raiseError ( `verifyApplicableRefactorAvailableForRange failed - expected no refactor but found some.` ) ;
30113003 }
@@ -3016,7 +3008,7 @@ Actual: ${stringify(fullActual)}`);
30163008
30173009 public applyRefactor ( { refactorName, actionName, actionDescription, newContent : newContentWithRenameMarker } : FourSlashInterface . ApplyRefactorOptions ) {
30183010 const range = this . getSelection ( ) ;
3019- const refactors = this . languageService . getApplicableRefactors ( this . activeFile . fileName , range , ts . defaultPreferences ) ;
3011+ const refactors = this . getApplicableRefactors ( range ) ;
30203012 const refactorsWithName = refactors . filter ( r => r . name === refactorName ) ;
30213013 if ( refactorsWithName . length === 0 ) {
30223014 this . raiseError ( `The expected refactor: ${ refactorName } is not available at the marker location.\nAvailable refactors: ${ refactors . map ( r => r . name ) } ` ) ;
@@ -3062,7 +3054,38 @@ Actual: ${stringify(fullActual)}`);
30623054 return { renamePosition, newContent } ;
30633055 }
30643056 }
3057+ }
3058+
3059+ public moveToNewFile ( options : FourSlashInterface . MoveToNewFileOptions ) : void {
3060+ assert ( this . getRanges ( ) . length === 1 ) ;
3061+ const range = this . getRanges ( ) [ 0 ] ;
3062+ const refactor = ts . find ( this . getApplicableRefactors ( range ) , r => r . name === "Move to new file" ) ;
3063+ assert ( refactor . actions . length === 1 ) ;
3064+ const action = ts . first ( refactor . actions ) ;
3065+ assert ( action . name === "Move to new file" && action . description === "Move to new file" ) ;
3066+
3067+ const editInfo = this . languageService . getEditsForRefactor ( this . activeFile . fileName , this . formatCodeSettings , range , refactor . name , action . name , ts . defaultPreferences ) ;
3068+ for ( const edit of editInfo . edits ) {
3069+ const newContent = options . newFileContents [ edit . fileName ] ;
3070+ if ( newContent === undefined ) {
3071+ this . raiseError ( `There was an edit in ${ edit . fileName } but new content was not specified.` ) ;
3072+ }
3073+ if ( this . testData . files . some ( f => f . fileName === edit . fileName ) ) {
3074+ this . applyEdits ( edit . fileName , edit . textChanges , /*isFormattingEdit*/ false ) ;
3075+ this . openFile ( edit . fileName ) ;
3076+ this . verifyCurrentFileContent ( newContent ) ;
3077+ }
3078+ else {
3079+ assert ( edit . textChanges . length === 1 ) ;
3080+ const change = ts . first ( edit . textChanges ) ;
3081+ assert . deepEqual ( change . span , ts . createTextSpan ( 0 , 0 ) ) ;
3082+ assert . equal ( change . newText , newContent , `Content for ${ edit . fileName } ` ) ;
3083+ }
3084+ }
30653085
3086+ for ( const fileName in options . newFileContents ) {
3087+ assert ( editInfo . edits . some ( e => e . fileName === fileName ) ) ;
3088+ }
30663089 }
30673090
30683091 public verifyFileAfterApplyingRefactorAtMarker (
@@ -3278,6 +3301,10 @@ Actual: ${stringify(fullActual)}`);
32783301 this . verifyCurrentFileContent ( options . newFileContents [ fileName ] ) ;
32793302 }
32803303 }
3304+
3305+ private getApplicableRefactors ( positionOrRange : number | ts . TextRange ) : ReadonlyArray < ts . ApplicableRefactorInfo > {
3306+ return this . languageService . getApplicableRefactors ( this . activeFile . fileName , positionOrRange , ts . defaultPreferences ) || ts . emptyArray ;
3307+ }
32813308 }
32823309
32833310 export function runFourSlashTest ( basePath : string , testType : FourSlashTestType , fileName : string ) {
@@ -4373,6 +4400,10 @@ namespace FourSlashInterface {
43734400 public getEditsForFileRename ( options : GetEditsForFileRenameOptions ) {
43744401 this . state . getEditsForFileRename ( options ) ;
43754402 }
4403+
4404+ public moveToNewFile ( options : MoveToNewFileOptions ) : void {
4405+ this . state . moveToNewFile ( options ) ;
4406+ }
43764407 }
43774408
43784409 export class Edit {
@@ -4721,4 +4752,8 @@ namespace FourSlashInterface {
47214752 readonly newPath : string ;
47224753 readonly newFileContents : { readonly [ fileName : string ] : string } ;
47234754 }
4755+
4756+ export interface MoveToNewFileOptions {
4757+ readonly newFileContents : { readonly [ fileName : string ] : string } ;
4758+ }
47244759}
0 commit comments