@@ -8,7 +8,7 @@ namespace ts.refactor.extractSymbol {
88 * Exported for tests.
99 */
1010 export function getAvailableActions ( context : RefactorContext ) : readonly ApplicableRefactorInfo [ ] {
11- const rangeToExtract = getRangeToExtract ( context . file , getRefactorContextSpan ( context ) ) ;
11+ const rangeToExtract = getRangeToExtract ( context . file , getRefactorContextSpan ( context ) , context . triggerReason === "invoked" ) ;
1212
1313 const targetRange = rangeToExtract . targetRange ;
1414 if ( targetRange === undefined ) {
@@ -186,18 +186,20 @@ namespace ts.refactor.extractSymbol {
186186 * not shown to the user, but can be used by us diagnostically)
187187 */
188188 // exported only for tests
189- export function getRangeToExtract ( sourceFile : SourceFile , span : TextSpan ) : RangeToExtract {
189+ export function getRangeToExtract ( sourceFile : SourceFile , span : TextSpan , considerEmptySpans = true ) : RangeToExtract {
190190 const { length } = span ;
191-
192- if ( length === 0 ) {
191+ if ( length === 0 && ! considerEmptySpans ) {
193192 return { errors : [ createFileDiagnostic ( sourceFile , span . start , length , Messages . cannotExtractEmpty ) ] } ;
194193 }
194+ const cursorRequest = length === 0 && considerEmptySpans ;
195195
196196 // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span.
197197 // This may fail (e.g. you select two statements in the root of a source file)
198- const start = getParentNodeInSpan ( getTokenAtPosition ( sourceFile , span . start ) , sourceFile , span ) ;
198+ const startToken = getTokenAtPosition ( sourceFile , span . start ) ;
199+ const start = cursorRequest ? getExtractableParent ( startToken ) : getParentNodeInSpan ( startToken , sourceFile , span ) ;
199200 // Do the same for the ending position
200- const end = getParentNodeInSpan ( findTokenOnLeftOfPosition ( sourceFile , textSpanEnd ( span ) ) , sourceFile , span ) ;
201+ const endToken = findTokenOnLeftOfPosition ( sourceFile , textSpanEnd ( span ) ) ;
202+ const end = cursorRequest ? start : getParentNodeInSpan ( endToken , sourceFile , span ) ;
201203
202204 const declarations : Symbol [ ] = [ ] ;
203205
@@ -1846,6 +1848,10 @@ namespace ts.refactor.extractSymbol {
18461848 }
18471849 }
18481850
1851+ function getExtractableParent ( node : Node | undefined ) : Node | undefined {
1852+ return findAncestor ( node , node => node . parent && isExtractableExpression ( node ) && ! isBinaryExpression ( node . parent ) ) ;
1853+ }
1854+
18491855 /**
18501856 * Computes whether or not a node represents an expression in a position where it could
18511857 * be extracted.
0 commit comments