@@ -697,8 +697,14 @@ namespace ts.refactor.extractMethod {
697
697
}
698
698
699
699
const changeTracker = textChanges . ChangeTracker . fromContext ( context ) ;
700
- // insert function at the end of the scope
701
- changeTracker . insertNodeBefore ( context . file , scope . getLastToken ( ) , newFunction , { prefix : context . newLineCharacter , suffix : context . newLineCharacter } ) ;
700
+ const minInsertionPos = ( isReadonlyArray ( range . range ) ? lastOrUndefined ( range . range ) : range . range ) . end ;
701
+ const nodeToInsertBefore = getNodeToInsertBefore ( minInsertionPos , scope ) ;
702
+ if ( nodeToInsertBefore ) {
703
+ changeTracker . insertNodeBefore ( context . file , nodeToInsertBefore , newFunction , { suffix : context . newLineCharacter + context . newLineCharacter } ) ;
704
+ }
705
+ else {
706
+ changeTracker . insertNodeBefore ( context . file , scope . getLastToken ( ) , newFunction , { prefix : context . newLineCharacter , suffix : context . newLineCharacter } ) ;
707
+ }
702
708
703
709
const newNodes : Node [ ] = [ ] ;
704
710
// replace range with function call
@@ -831,6 +837,39 @@ namespace ts.refactor.extractMethod {
831
837
return "__return" ;
832
838
}
833
839
840
+ function getStatementsOrClassElements ( scope : Scope ) : ReadonlyArray < Statement > | ReadonlyArray < ClassElement > {
841
+ if ( isFunctionLike ( scope ) ) {
842
+ const body = scope . body ;
843
+ if ( isBlock ( body ) ) {
844
+ return body . statements ;
845
+ }
846
+ }
847
+ else if ( isModuleBlock ( scope ) || isSourceFile ( scope ) ) {
848
+ return scope . statements ;
849
+ }
850
+ else if ( isClassLike ( scope ) ) {
851
+ return scope . members ;
852
+ }
853
+ else {
854
+ staticAssertNever ( scope ) ;
855
+ }
856
+
857
+ return emptyArray ;
858
+ }
859
+
860
+ /**
861
+ * If `scope` contains a function after `minPos`, then return the first such function.
862
+ * Otherwise, return `undefined`.
863
+ */
864
+ function getNodeToInsertBefore ( minPos : number , scope : Scope ) : Node | undefined {
865
+ const children = getStatementsOrClassElements ( scope ) ;
866
+ for ( const child of children ) {
867
+ if ( child . pos >= minPos && isFunctionLike ( child ) && ! isConstructorDeclaration ( child ) ) {
868
+ return child ;
869
+ }
870
+ }
871
+ }
872
+
834
873
function transformFunctionBody ( body : Node ) {
835
874
if ( isBlock ( body ) && ! writes && substitutions . size === 0 ) {
836
875
// already block, no writes to propagate back, no substitutions - can use node as is
0 commit comments