mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-12 04:17:34 -06:00
Test that the return type of the extracted method counts as usage
This commit is contained in:
parent
0c8d85fbc4
commit
01d7f0b699
@ -581,6 +581,11 @@ namespace A {
|
||||
function F<U extends T[]>(t2: U) {
|
||||
[#|t2.toString();|]
|
||||
}
|
||||
}`);
|
||||
// Confirm that the contextual type of an extracted expression counts as a use.
|
||||
testExtractMethod("extractMethod16",
|
||||
`function F<T>() {
|
||||
const array: T[] = [#|[]|];
|
||||
}`);
|
||||
});
|
||||
|
||||
|
||||
@ -946,6 +946,7 @@ namespace ts.refactor.extractMethod {
|
||||
substitutionsPerScope.push(createMap<Expression>());
|
||||
errorsPerScope.push([]);
|
||||
}
|
||||
|
||||
const seenUsages = createMap<Usage>();
|
||||
const target = isReadonlyArray(targetRange.range) ? createBlock(<Statement[]>targetRange.range) : targetRange.range;
|
||||
const containingLexicalScopeOfExtraction = isBlockScope(scopes[0], scopes[0].parent) ? scopes[0] : getEnclosingBlockScopeContainer(scopes[0]);
|
||||
@ -955,6 +956,14 @@ namespace ts.refactor.extractMethod {
|
||||
|
||||
collectUsages(target);
|
||||
|
||||
// Unfortunately, this code takes advantage of the knowledge that the generated method
|
||||
// will use the contextual type of an expression as the return type of the extracted
|
||||
// method (and will therefore "use" all the types involved).
|
||||
if (inGenericContext && !isReadonlyArray(targetRange.range)) {
|
||||
const contextualType = checker.getContextualType(targetRange.range);
|
||||
recordTypeParameterUsages(contextualType);
|
||||
}
|
||||
|
||||
if (allTypeParameterUsages.size > 0) {
|
||||
const seenTypeParameterUsages = createMap<TypeParameter>(); // Key is type ID
|
||||
|
||||
@ -1032,18 +1041,21 @@ namespace ts.refactor.extractMethod {
|
||||
return false;
|
||||
}
|
||||
|
||||
function recordTypeParameterUsages(type: Type) {
|
||||
const symbolWalker = checker.getSymbolWalker();
|
||||
const {visitedTypes} = symbolWalker.walkType(type);
|
||||
|
||||
for (const visitedType of visitedTypes) {
|
||||
if (visitedType.flags & TypeFlags.TypeParameter) {
|
||||
allTypeParameterUsages.set(visitedType.id.toString(), visitedType as TypeParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function collectUsages(node: Node, valueUsage = Usage.Read) {
|
||||
if (inGenericContext) {
|
||||
const type = checker.getTypeAtLocation(node);
|
||||
|
||||
const symbolWalker = checker.getSymbolWalker();
|
||||
const {visitedTypes} = symbolWalker.walkType(type);
|
||||
|
||||
for (const visitedType of visitedTypes) {
|
||||
if (visitedType.flags & TypeFlags.TypeParameter) {
|
||||
allTypeParameterUsages.set(visitedType.id.toString(), visitedType as TypeParameter);
|
||||
}
|
||||
}
|
||||
recordTypeParameterUsages(type);
|
||||
}
|
||||
|
||||
if (isDeclaration(node) && node.symbol) {
|
||||
|
||||
19
tests/baselines/reference/extractMethod/extractMethod16.ts
Normal file
19
tests/baselines/reference/extractMethod/extractMethod16.ts
Normal file
@ -0,0 +1,19 @@
|
||||
// ==ORIGINAL==
|
||||
function F<T>() {
|
||||
const array: T[] = [];
|
||||
}
|
||||
// ==SCOPE::function 'F'==
|
||||
function F<T>() {
|
||||
const array: T[] = newFunction();
|
||||
|
||||
function newFunction(): T[] {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
// ==SCOPE::global scope==
|
||||
function F<T>() {
|
||||
const array: T[] = newFunction<T>();
|
||||
}
|
||||
function newFunction<T>(): T[] {
|
||||
return [];
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user