diff --git a/src/services/codefixes/generateAccessors.ts b/src/services/codefixes/generateAccessors.ts index 904e52d29c5..3c9e82e157c 100644 --- a/src/services/codefixes/generateAccessors.ts +++ b/src/services/codefixes/generateAccessors.ts @@ -104,9 +104,9 @@ namespace ts.codefix { return modifierFlags; } - export function getAccessorConvertiblePropertyAtPosition(file: SourceFile, start: number, end: number, userRequested = true): Info | undefined { + export function getAccessorConvertiblePropertyAtPosition(file: SourceFile, start: number, end: number, considerEmptySpans = true): Info | undefined { const node = getTokenAtPosition(file, start); - const cursorRequest = start === end && userRequested; + const cursorRequest = start === end && considerEmptySpans; const declaration = findAncestor(node.parent, isAcceptedDeclaration); // make sure declaration have AccessibilityModifier or Static Modifier or Readonly Modifier const meaning = ModifierFlags.AccessibilityModifier | ModifierFlags.Static | ModifierFlags.Readonly; diff --git a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts index 84e596c5e41..5a11b862dd8 100644 --- a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts +++ b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts @@ -70,12 +70,12 @@ namespace ts.refactor.addOrRemoveBracesToArrowFunction { return { renameFilename: undefined, renameLocation: undefined, edits }; } - function getConvertibleArrowFunctionAtPosition(file: SourceFile, startPosition: number, userRequested = true): Info | undefined { + function getConvertibleArrowFunctionAtPosition(file: SourceFile, startPosition: number, considerFunctionBodies = true): Info | undefined { const node = getTokenAtPosition(file, startPosition); const func = getContainingFunction(node); // Only offer a refactor in the function body on explicit refactor requests. if (!func || !isArrowFunction(func) || (!rangeContainsRange(func, node) - || (rangeContainsRange(func.body, node) && !userRequested))) return undefined; + || (rangeContainsRange(func.body, node) && !considerFunctionBodies))) return undefined; if (isExpression(func.body)) { return { diff --git a/src/services/refactors/convertExport.ts b/src/services/refactors/convertExport.ts index b6440de2284..c79833db1ea 100644 --- a/src/services/refactors/convertExport.ts +++ b/src/services/refactors/convertExport.ts @@ -27,12 +27,11 @@ namespace ts.refactor { readonly exportingModuleSymbol: Symbol; } - function getInfo(context: RefactorContext, userRequested = true): Info | undefined { + function getInfo(context: RefactorContext, considerPartialSpans = true): Info | undefined { const { file } = context; const span = getRefactorContextSpan(context); const token = getTokenAtPosition(file, span.start); - const cursorRequest = userRequested && span; - const exportNode = !!(getSyntacticModifierFlags(token.parent) & ModifierFlags.Export) && cursorRequest ? token.parent : getParentNodeInSpan(token, file, span); + const exportNode = !!(token.parent && getSyntacticModifierFlags(token.parent) & ModifierFlags.Export) && considerPartialSpans ? token.parent : getParentNodeInSpan(token, file, span); if (!exportNode || (!isSourceFile(exportNode.parent) && !(isModuleBlock(exportNode.parent) && isAmbientModule(exportNode.parent.parent)))) { return undefined; } diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index 88c501925c1..1383aa18ddb 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -19,12 +19,11 @@ namespace ts.refactor { }); // Can convert imports of the form `import * as m from "m";` or `import d, { x, y } from "m";`. - function getImportToConvert(context: RefactorContext, userRequested = true): NamedImportBindings | undefined { + function getImportToConvert(context: RefactorContext, considerPartialSpans = true): NamedImportBindings | undefined { const { file } = context; const span = getRefactorContextSpan(context); const token = getTokenAtPosition(file, span.start); - const cursorRequest = userRequested && span.length === 0; - const importDecl = cursorRequest ? findAncestor(token, isImportDeclaration) : getParentNodeInSpan(token, file, span); + const importDecl = considerPartialSpans ? findAncestor(token, isImportDeclaration) : getParentNodeInSpan(token, file, span); if (!importDecl || !isImportDeclaration(importDecl) || (importDecl.getEnd() < span.start + span.length)) return undefined; const { importClause } = importDecl; return importClause && importClause.namedBindings; diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 3da484a9ce6..5c274ffbe18 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -186,12 +186,12 @@ namespace ts.refactor.extractSymbol { * not shown to the user, but can be used by us diagnostically) */ // exported only for tests - export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, userRequested = true): RangeToExtract { + export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, considerEmptySpans = true): RangeToExtract { const { length } = span; - if (length === 0 && !userRequested) { + if (length === 0 && !considerEmptySpans) { return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractEmpty)] }; } - const cursorRequest = length === 0 && userRequested; + const cursorRequest = length === 0 && considerEmptySpans; // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span. // This may fail (e.g. you select two statements in the root of a source file) diff --git a/src/services/refactors/extractType.ts b/src/services/refactors/extractType.ts index 4941c4dffd6..491fec63bd0 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -58,12 +58,12 @@ namespace ts.refactor { type Info = TypeAliasInfo | InterfaceInfo; - function getRangeToExtract(context: RefactorContext, userRequested = true): Info | undefined { + function getRangeToExtract(context: RefactorContext, considerEmptySpans = true): Info | undefined { const { file, startPosition } = context; const isJS = isSourceFileJS(file); const current = getTokenAtPosition(file, startPosition); const range = createTextRangeFromSpan(getRefactorContextSpan(context)); - const cursorRequest = range.pos === range.end && userRequested; + const cursorRequest = range.pos === range.end && considerEmptySpans; const selection = findAncestor(current, (node => node.parent && isTypeNode(node) && !rangeContainsSkipTrivia(range, node.parent, file) && (cursorRequest || nodeOverlapsWithStartEnd(current, file, range.pos, range.end)))); diff --git a/tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason.ts b/tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason1.ts similarity index 82% rename from tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason.ts rename to tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason1.ts index a1e940fa7b1..4f5e41a8e3a 100644 --- a/tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason.ts +++ b/tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason1.ts @@ -2,7 +2,7 @@ //// const a = (a: number) => { return/*a*//*b*/ a; }; -// Only offer refactor for empty span if explicity requested +// Only offer refactor for empty span in body if explicity requested goTo.select("a", "b"); verify.not.refactorAvailableForTriggerReason("implicit", "Add or remove braces in an arrow function"); verify.refactorAvailableForTriggerReason("invoked", "Add or remove braces in an arrow function", "Remove braces from arrow function"); diff --git a/tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason2.ts b/tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason2.ts new file mode 100644 index 00000000000..5677e2c7144 --- /dev/null +++ b/tests/cases/fourslash/refactorAddOrRemoveBracesToArrowFunctionForTriggerReason2.ts @@ -0,0 +1,8 @@ +/// + +//// const a = (a: number) => { re/*a*/tur/*b*/n a; }; + +// Only offer refactor in body if explicity requested +goTo.select("a", "b"); +verify.not.refactorAvailableForTriggerReason("implicit", "Add or remove braces in an arrow function"); +verify.refactorAvailableForTriggerReason("invoked", "Add or remove braces in an arrow function", "Remove braces from arrow function"); diff --git a/tests/cases/fourslash/refactorConvertImportForTriggerReason.ts b/tests/cases/fourslash/refactorConvertImportForTriggerReason1.ts similarity index 100% rename from tests/cases/fourslash/refactorConvertImportForTriggerReason.ts rename to tests/cases/fourslash/refactorConvertImportForTriggerReason1.ts diff --git a/tests/cases/fourslash/refactorConvertImportForTriggerReason2.ts b/tests/cases/fourslash/refactorConvertImportForTriggerReason2.ts new file mode 100644 index 00000000000..1404ade7348 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertImportForTriggerReason2.ts @@ -0,0 +1,8 @@ +/// + +////import d, * as /*a*/n/*b*/ from "m"; + +// Only offer refactor for sub span if explicity requested +goTo.select("a", "b"); +verify.not.refactorAvailableForTriggerReason("implicit", "Convert import"); +verify.refactorAvailableForTriggerReason("invoked", "Convert import"); diff --git a/tests/cases/fourslash/refactorExtractTypeForTriggerReason.ts b/tests/cases/fourslash/refactorExtractTypeForTriggerReason1.ts similarity index 100% rename from tests/cases/fourslash/refactorExtractTypeForTriggerReason.ts rename to tests/cases/fourslash/refactorExtractTypeForTriggerReason1.ts diff --git a/tests/cases/fourslash/refactorExtractTypeForTriggerReason2.ts b/tests/cases/fourslash/refactorExtractTypeForTriggerReason2.ts new file mode 100644 index 00000000000..0f81c3cc88b --- /dev/null +++ b/tests/cases/fourslash/refactorExtractTypeForTriggerReason2.ts @@ -0,0 +1,7 @@ +/// + +//// var x: s/*a*/tr/*b*/ing; + +goTo.select("a", "b"); +verify.refactorAvailableForTriggerReason("implicit", "Extract type"); +verify.refactorAvailableForTriggerReason("invoked", "Extract type");