Merge pull request #13658 from Microsoft/findallrefs_mappedtypes

Support find-all-references on mapped types.
This commit is contained in:
Andy 2017-01-24 13:31:48 -08:00 committed by GitHub
commit c55b9ffe83
5 changed files with 25 additions and 6 deletions

View file

@ -4618,12 +4618,14 @@ namespace ts {
const typeParameter = getTypeParameterFromMappedType(type);
const constraintType = getConstraintTypeFromMappedType(type);
const templateType = getTemplateTypeFromMappedType(type);
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type));
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
const templateReadonly = !!type.declaration.readonlyToken;
const templateOptional = !!type.declaration.questionToken;
if (type.declaration.typeParameter.constraint.kind === SyntaxKind.TypeOperator) {
// We have a { [P in keyof T]: X }
forEachType(getLiteralTypeFromPropertyNames(modifiersType), addMemberForKeyType);
for (const propertySymbol of getPropertiesOfType(modifiersType)) {
addMemberForKeyType(getLiteralTypeFromPropertyName(propertySymbol), propertySymbol);
}
if (getIndexInfoOfType(modifiersType, IndexKind.String)) {
addMemberForKeyType(stringType);
}
@ -4638,7 +4640,7 @@ namespace ts {
}
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
function addMemberForKeyType(t: Type) {
function addMemberForKeyType(t: Type, propertySymbol?: Symbol) {
// Create a mapper from T to the current iteration type constituent. Then, if the
// mapped type is itself an instantiated type, combine the iteration mapper with the
// instantiation mapper.
@ -4654,6 +4656,9 @@ namespace ts {
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName);
prop.type = propType;
prop.isReadonly = templateReadonly || modifiersProp && isReadonlySymbol(modifiersProp);
if (propertySymbol) {
prop.mappedTypeOrigin = propertySymbol;
}
members.set(propName, prop);
}
else if (t.flags & TypeFlags.String) {
@ -20233,6 +20238,10 @@ namespace ts {
const links = symbol as SymbolLinks;
return [links.leftSpread, links.rightSpread];
}
if ((symbol as SymbolLinks).mappedTypeOrigin) {
return getRootSymbols((symbol as SymbolLinks).mappedTypeOrigin);
}
let target: Symbol;
let next = symbol;
while (next = getSymbolLinks(next).target) {

View file

@ -2712,6 +2712,7 @@
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
leftSpread?: Symbol; // Left source for synthetic spread property
rightSpread?: Symbol; // Right source for synthetic spread property
mappedTypeOrigin?: Symbol; // For a property on a mapped type, points back to the orignal 'T' from 'keyof T'.
hasNonUniformType?: boolean; // True if constituents have non-uniform types
isPartial?: boolean; // True if syntheric property of union type occurs in some but not all constituents
isDiscriminantProperty?: boolean; // True if discriminant synthetic property

View file

@ -139,9 +139,9 @@ declare let x2: string;
declare let x3: number;
declare let x4: {
toString: void;
valueOf: void;
toFixed: void;
toExponential: void;
toPrecision: void;
valueOf: void;
toLocaleString: void;
};

View file

@ -165,7 +165,7 @@ let x3 = f3();
>f3 : <T1 extends number>() => { [P in keyof T1]: void; }
let x4 = f4();
>x4 : { toString: void; valueOf: void; toFixed: void; toExponential: void; toPrecision: void; toLocaleString: void; }
>f4() : { toString: void; valueOf: void; toFixed: void; toExponential: void; toPrecision: void; toLocaleString: void; }
>x4 : { toString: void; toFixed: void; toExponential: void; toPrecision: void; valueOf: void; toLocaleString: void; }
>f4() : { toString: void; toFixed: void; toExponential: void; toPrecision: void; valueOf: void; toLocaleString: void; }
>f4 : <T1 extends Number>() => { [P in keyof T1]: void; }

View file

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts'/>
////interface T { [|a|]: number };
////type U { [K in keyof T]: string };
////type V = { [K in keyof U]: boolean };
////const u: U = { [|a|]: "" }
////const v: V = { [|a|]: true }
verify.rangesReferenceEachOther();