mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Merge pull request #861 from Microsoft/unionTypesLS
Lanugage Service support for union types
This commit is contained in:
commit
eee1602b70
@ -88,7 +88,7 @@ module ts {
|
||||
symbolToString: symbolToString,
|
||||
symbolToDisplayParts: symbolToDisplayParts,
|
||||
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType,
|
||||
getRootSymbol: getRootSymbol,
|
||||
getRootSymbols: getRootSymbols,
|
||||
getContextualType: getContextualType,
|
||||
getFullyQualifiedName: getFullyQualifiedName,
|
||||
getResolvedSignature: getResolvedSignature,
|
||||
@ -2144,6 +2144,14 @@ module ts {
|
||||
}
|
||||
var symbol = <TransientSymbol>createSymbol(SymbolFlags.UnionProperty | SymbolFlags.Transient, prop.name);
|
||||
symbol.unionType = type;
|
||||
|
||||
symbol.declarations = [];
|
||||
for (var i = 0; i < types.length; i++) {
|
||||
var s = getPropertyOfType(types[i], prop.name);
|
||||
if (s.declarations)
|
||||
symbol.declarations.push.apply(symbol.declarations, s.declarations);
|
||||
}
|
||||
|
||||
members[prop.name] = symbol;
|
||||
});
|
||||
var callSignatures = getUnionSignatures(types, SignatureKind.Call);
|
||||
@ -3635,7 +3643,8 @@ module ts {
|
||||
}
|
||||
|
||||
function getBestCommonType(types: Type[], contextualType: Type): Type {
|
||||
return contextualType && isSupertypeOfEach(contextualType, types) ? contextualType : getUnionType(types);
}
|
||||
return contextualType && isSupertypeOfEach(contextualType, types) ? contextualType : getUnionType(types);
|
||||
}
|
||||
|
||||
function isTypeOfObjectLiteral(type: Type): boolean {
|
||||
return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false;
|
||||
@ -7928,8 +7937,22 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getRootSymbol(symbol: Symbol) {
|
||||
return ((symbol.flags & SymbolFlags.Transient) && getSymbolLinks(symbol).target) || symbol;
|
||||
function getRootSymbols(symbol: Symbol): Symbol[] {
|
||||
if (symbol.flags & SymbolFlags.UnionProperty) {
|
||||
var symbols: Symbol[] = [];
|
||||
var name = symbol.name;
|
||||
forEach(getSymbolLinks(symbol).unionType.types, t => {
|
||||
symbols.push(getPropertyOfType(getApparentType(t), name));
|
||||
});
|
||||
return symbols;
|
||||
}
|
||||
else if (symbol.flags & SymbolFlags.Transient) {
|
||||
var target = getSymbolLinks(symbol).target;
|
||||
if (target) {
|
||||
return [target];
|
||||
}
|
||||
}
|
||||
return [symbol];
|
||||
}
|
||||
|
||||
// Emitter support
|
||||
|
||||
@ -653,7 +653,7 @@ module ts {
|
||||
symbolToDisplayParts(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): SymbolDisplayPart[];
|
||||
getFullyQualifiedName(symbol: Symbol): string;
|
||||
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
|
||||
getRootSymbol(symbol: Symbol): Symbol;
|
||||
getRootSymbols(symbol: Symbol): Symbol[];
|
||||
getContextualType(node: Node): Type;
|
||||
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
|
||||
|
||||
|
||||
@ -2322,7 +2322,7 @@ module ts {
|
||||
}
|
||||
|
||||
function getSymbolKind(symbol: Symbol): string {
|
||||
var flags = typeInfoResolver.getRootSymbol(symbol).getFlags();
|
||||
var flags = typeInfoResolver.getRootSymbols(symbol)[0].getFlags();
|
||||
|
||||
if (flags & SymbolFlags.Module) return ScriptElementKind.moduleElement;
|
||||
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
|
||||
@ -2404,31 +2404,34 @@ module ts {
|
||||
|
||||
var documentationParts = getSymbolDocumentationDisplayParts(symbol);
|
||||
|
||||
// TODO: handle union properties appropriately when merging with master
|
||||
var symbolFlags = typeInfoResolver.getRootSymbols(symbol)[0].flags;
|
||||
|
||||
// Having all this logic here is pretty unclean. Consider moving to the roslyn model
|
||||
// where all symbol display logic is encapsulated into visitors and options.
|
||||
var totalParts: SymbolDisplayPart[] = [];
|
||||
|
||||
if (symbol.flags & SymbolFlags.Class) {
|
||||
if (symbolFlags & SymbolFlags.Class) {
|
||||
totalParts.push(keywordPart(SyntaxKind.ClassKeyword));
|
||||
totalParts.push(spacePart());
|
||||
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile));
|
||||
}
|
||||
else if (symbol.flags & SymbolFlags.Interface) {
|
||||
else if (symbolFlags & SymbolFlags.Interface) {
|
||||
totalParts.push(keywordPart(SyntaxKind.InterfaceKeyword));
|
||||
totalParts.push(spacePart());
|
||||
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile));
|
||||
}
|
||||
else if (symbol.flags & SymbolFlags.Enum) {
|
||||
else if (symbolFlags & SymbolFlags.Enum) {
|
||||
totalParts.push(keywordPart(SyntaxKind.EnumKeyword));
|
||||
totalParts.push(spacePart());
|
||||
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile));
|
||||
}
|
||||
else if (symbol.flags & SymbolFlags.Module) {
|
||||
else if (symbolFlags & SymbolFlags.Module) {
|
||||
totalParts.push(keywordPart(SyntaxKind.ModuleKeyword));
|
||||
totalParts.push(spacePart());
|
||||
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile));
|
||||
}
|
||||
else if (symbol.flags & SymbolFlags.TypeParameter) {
|
||||
else if (symbolFlags & SymbolFlags.TypeParameter) {
|
||||
totalParts.push(punctuationPart(SyntaxKind.OpenParenToken));
|
||||
totalParts.push(new SymbolDisplayPart("type parameter", SymbolDisplayPartKind.text, undefined));
|
||||
totalParts.push(punctuationPart(SyntaxKind.CloseParenToken));
|
||||
@ -2439,11 +2442,11 @@ module ts {
|
||||
totalParts.push(punctuationPart(SyntaxKind.OpenParenToken));
|
||||
var text: string;
|
||||
|
||||
if (symbol.flags & SymbolFlags.Property) { text = "property" }
|
||||
else if (symbol.flags & SymbolFlags.EnumMember) { text = "enum member" }
|
||||
else if (symbol.flags & SymbolFlags.Function) { text = "function" }
|
||||
else if (symbol.flags & SymbolFlags.Variable) { text = "variable" }
|
||||
else if (symbol.flags & SymbolFlags.Method) { text = "method" }
|
||||
if (symbolFlags & SymbolFlags.Property) { text = "property" }
|
||||
else if (symbolFlags & SymbolFlags.EnumMember) { text = "enum member" }
|
||||
else if (symbolFlags & SymbolFlags.Function) { text = "function" }
|
||||
else if (symbolFlags & SymbolFlags.Variable) { text = "variable" }
|
||||
else if (symbolFlags & SymbolFlags.Method) { text = "method" }
|
||||
|
||||
if (!text) {
|
||||
return undefined;
|
||||
@ -2457,8 +2460,8 @@ module ts {
|
||||
|
||||
var type = typeInfoResolver.getTypeOfSymbol(symbol);
|
||||
|
||||
if (symbol.flags & SymbolFlags.Property ||
|
||||
symbol.flags & SymbolFlags.Variable) {
|
||||
if (symbolFlags & SymbolFlags.Property ||
|
||||
symbolFlags & SymbolFlags.Variable) {
|
||||
|
||||
if (type) {
|
||||
totalParts.push(punctuationPart(SyntaxKind.ColonToken));
|
||||
@ -2466,13 +2469,13 @@ module ts {
|
||||
totalParts.push.apply(totalParts, typeInfoResolver.typeToDisplayParts(type, getContainerNode(node)));
|
||||
}
|
||||
}
|
||||
else if (symbol.flags & SymbolFlags.Function ||
|
||||
symbol.flags & SymbolFlags.Method) {
|
||||
else if (symbolFlags & SymbolFlags.Function ||
|
||||
symbolFlags & SymbolFlags.Method) {
|
||||
if (type) {
|
||||
totalParts.push.apply(totalParts, typeInfoResolver.typeToDisplayParts(type, getContainerNode(node)));
|
||||
}
|
||||
}
|
||||
else if (symbol.flags & SymbolFlags.EnumMember) {
|
||||
else if (symbolFlags & SymbolFlags.EnumMember) {
|
||||
var declaration = symbol.declarations[0];
|
||||
if (declaration.kind === SyntaxKind.EnumMember) {
|
||||
var constantValue = typeInfoResolver.getEnumMemberValue(<EnumMember>declaration);
|
||||
@ -2521,7 +2524,7 @@ module ts {
|
||||
}
|
||||
|
||||
/// Goto definition
|
||||
function getDefinitionAtPosition(filename: string, position: number): DefinitionInfo[]{
|
||||
function getDefinitionAtPosition(filename: string, position: number): DefinitionInfo[] {
|
||||
function getDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo {
|
||||
return {
|
||||
fileName: node.getSourceFile().filename,
|
||||
@ -2553,7 +2556,7 @@ module ts {
|
||||
result.push(getDefinitionInfo(declarations[declarations.length - 1], symbolKind, symbolName, containerName));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2578,6 +2581,25 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getDefinitionFromSymbol(symbol: Symbol, location: Node, result: DefinitionInfo[]): void {
|
||||
var declarations = symbol.getDeclarations();
|
||||
if (declarations) {
|
||||
var symbolName = typeInfoResolver.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
|
||||
var symbolKind = getSymbolKind(symbol);
|
||||
var containerSymbol = symbol.parent;
|
||||
var containerName = containerSymbol ? typeInfoResolver.symbolToString(containerSymbol, location) : "";
|
||||
var containerKind = containerSymbol ? getSymbolKind(symbol) : "";
|
||||
|
||||
if (!tryAddConstructSignature(symbol, location, symbolKind, symbolName, containerName, result) &&
|
||||
!tryAddCallSignature(symbol, location, symbolKind, symbolName, containerName, result)) {
|
||||
// Just add all the declarations.
|
||||
forEach(declarations, declaration => {
|
||||
result.push(getDefinitionInfo(declaration, symbolKind, symbolName, containerName));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronizeHostData();
|
||||
|
||||
filename = TypeScript.switchToForwardSlashes(filename);
|
||||
@ -2617,26 +2639,13 @@ module ts {
|
||||
|
||||
// Could not find a symbol e.g. node is string or number keyword,
|
||||
// or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
|
||||
if (!symbol || !(symbol.getDeclarations())) {
|
||||
if (!symbol) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var result: DefinitionInfo[] = [];
|
||||
|
||||
var declarations = symbol.getDeclarations();
|
||||
var symbolName = typeInfoResolver.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
|
||||
var symbolKind = getSymbolKind(symbol);
|
||||
var containerSymbol = symbol.parent;
|
||||
var containerName = containerSymbol ? typeInfoResolver.symbolToString(containerSymbol, node) : "";
|
||||
var containerKind = containerSymbol ? getSymbolKind(symbol) : "";
|
||||
|
||||
if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
|
||||
!tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) {
|
||||
// Just add all the declarations.
|
||||
forEach(declarations, declaration => {
|
||||
result.push(getDefinitionInfo(declaration, symbolKind, symbolName, containerName));
|
||||
});
|
||||
}
|
||||
getDefinitionFromSymbol(symbol, node, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -3151,18 +3160,20 @@ module ts {
|
||||
return [getReferenceEntryFromNode(node)];
|
||||
}
|
||||
|
||||
// the symbol was an internal symbol and does not have a declaration e.g.undefined symbol
|
||||
if (!symbol.getDeclarations()) {
|
||||
var declarations = symbol.declarations;
|
||||
|
||||
// The symbol was an internal symbol and does not have a declaration e.g.undefined symbol
|
||||
if (!declarations || !declarations.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var result: ReferenceEntry[];
|
||||
|
||||
// Compute the meaning from the location and the symbol it references
|
||||
var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.getDeclarations());
|
||||
var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
|
||||
|
||||
// Get the text to search for, we need to normalize it as external module names will have quote
|
||||
var symbolName = getNormalizedSymbolName(symbol);
|
||||
var symbolName = getNormalizedSymbolName(symbol.name, declarations);
|
||||
|
||||
// Get syntactic diagnostics
|
||||
var scope = getSymbolScope(symbol);
|
||||
@ -3184,15 +3195,15 @@ module ts {
|
||||
|
||||
return result;
|
||||
|
||||
function getNormalizedSymbolName(symbol: Symbol): string {
|
||||
function getNormalizedSymbolName(symbolName: string, declarations: Declaration[]): string {
|
||||
// Special case for function expressions, whose names are solely local to their bodies.
|
||||
var functionExpression = getDeclarationOfKind(symbol, SyntaxKind.FunctionExpression);
|
||||
var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? d : undefined);
|
||||
|
||||
if (functionExpression && functionExpression.name) {
|
||||
var name = functionExpression.name.text;
|
||||
}
|
||||
else {
|
||||
var name = symbol.name;
|
||||
var name = symbolName;
|
||||
}
|
||||
|
||||
var length = name.length;
|
||||
@ -3219,22 +3230,24 @@ module ts {
|
||||
var scope: Node = undefined;
|
||||
|
||||
var declarations = symbol.getDeclarations();
|
||||
for (var i = 0, n = declarations.length; i < n; i++) {
|
||||
var container = getContainerNode(declarations[i]);
|
||||
if (declarations) {
|
||||
for (var i = 0, n = declarations.length; i < n; i++) {
|
||||
var container = getContainerNode(declarations[i]);
|
||||
|
||||
if (scope && scope !== container) {
|
||||
// Different declarations have different containers, bail out
|
||||
return undefined;
|
||||
if (scope && scope !== container) {
|
||||
// Different declarations have different containers, bail out
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container)) {
|
||||
// This is a global variable and not an external module, any declaration defined
|
||||
// within this scope is visible outside the file
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// The search scope is the container node
|
||||
scope = container;
|
||||
}
|
||||
|
||||
if (container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container)) {
|
||||
// This is a global variable and not an external module, any declaration defined
|
||||
// within this scope is visible outside the file
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// The search scope is the container node
|
||||
scope = container;
|
||||
}
|
||||
|
||||
return scope;
|
||||
@ -3370,14 +3383,7 @@ module ts {
|
||||
}
|
||||
|
||||
var referenceSymbol = typeInfoResolver.getSymbolInfo(referenceLocation);
|
||||
|
||||
// Could not find a symbol e.g. node is string or number keyword,
|
||||
// or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
|
||||
if (!referenceSymbol || !(referenceSymbol.getDeclarations())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRelatableToSearchSet(searchSymbols, referenceSymbol, referenceLocation)) {
|
||||
if (referenceSymbol && isRelatableToSearchSet(searchSymbols, referenceSymbol, referenceLocation)) {
|
||||
result.push(getReferenceEntryFromNode(referenceLocation));
|
||||
}
|
||||
});
|
||||
@ -3539,24 +3545,27 @@ module ts {
|
||||
// The search set contains at least the current symbol
|
||||
var result = [symbol];
|
||||
|
||||
// If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
|
||||
var rootSymbol = typeInfoResolver.getRootSymbol(symbol);
|
||||
if (rootSymbol && rootSymbol !== symbol) {
|
||||
result.push(rootSymbol);
|
||||
}
|
||||
|
||||
// If the location is in a context sensitive location (i.e. in an object literal) try
|
||||
// to get a contextual type for it, and add the property symbol from the contextual
|
||||
// type to the search set
|
||||
if (isNameOfPropertyAssignment(location)) {
|
||||
var symbolFromContextualType = getPropertySymbolFromContextualType(location);
|
||||
if (symbolFromContextualType) result.push(typeInfoResolver.getRootSymbol(symbolFromContextualType));
|
||||
forEach(getPropertySymbolsFromContextualType(location), contextualSymbol => {
|
||||
result.push.apply(result, typeInfoResolver.getRootSymbols(contextualSymbol));
|
||||
});
|
||||
}
|
||||
|
||||
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
|
||||
if (symbol.parent && symbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
getPropertySymbolsFromBaseTypes(symbol.parent, symbol.getName(), result);
|
||||
}
|
||||
// If this is a union property, add all the symbols from all its source symbols in all unioned types.
|
||||
// If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
|
||||
forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => {
|
||||
if (rootSymbol !== symbol) {
|
||||
result.push(rootSymbol);
|
||||
}
|
||||
|
||||
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
|
||||
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -3592,11 +3601,7 @@ module ts {
|
||||
}
|
||||
|
||||
function isRelatableToSearchSet(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node): boolean {
|
||||
// Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)
|
||||
var referenceSymbolTarget = typeInfoResolver.getRootSymbol(referenceSymbol);
|
||||
|
||||
// if it is in the list, then we are done
|
||||
if (searchSymbols.indexOf(referenceSymbolTarget) >= 0) {
|
||||
if (searchSymbols.indexOf(referenceSymbol) >= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3604,29 +3609,61 @@ module ts {
|
||||
// object literal, lookup the property symbol in the contextual type, and use this symbol to
|
||||
// compare to our searchSymbol
|
||||
if (isNameOfPropertyAssignment(referenceLocation)) {
|
||||
var symbolFromContextualType = getPropertySymbolFromContextualType(referenceLocation);
|
||||
if (symbolFromContextualType && searchSymbols.indexOf(typeInfoResolver.getRootSymbol(symbolFromContextualType)) >= 0) {
|
||||
return forEach(getPropertySymbolsFromContextualType(referenceLocation), contextualSymbol => {
|
||||
return forEach(typeInfoResolver.getRootSymbols(contextualSymbol), s => searchSymbols.indexOf(s) >= 0);
|
||||
});
|
||||
}
|
||||
|
||||
// Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)
|
||||
// Or a union property, use its underlying unioned symbols
|
||||
return forEach(typeInfoResolver.getRootSymbols(referenceSymbol), rootSymbol => {
|
||||
// if it is in the list, then we are done
|
||||
if (searchSymbols.indexOf(rootSymbol) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, try all properties with the same name in any type the containing type extend or implemented, and
|
||||
// see if any is in the list
|
||||
if (referenceSymbol.parent && referenceSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
var result: Symbol[] = [];
|
||||
getPropertySymbolsFromBaseTypes(referenceSymbol.parent, referenceSymbol.getName(), result);
|
||||
return forEach(result, s => searchSymbols.indexOf(s) >= 0);
|
||||
}
|
||||
// Finally, try all properties with the same name in any type the containing type extended or implemented, and
|
||||
// see if any is in the list
|
||||
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
var result: Symbol[] = [];
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result);
|
||||
return forEach(result, s => searchSymbols.indexOf(s) >= 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function getPropertySymbolFromContextualType(node: Node): Symbol {
|
||||
function getPropertySymbolsFromContextualType(node: Node): Symbol[] {
|
||||
if (isNameOfPropertyAssignment(node)) {
|
||||
var objectLiteral = node.parent.parent;
|
||||
var contextualType = typeInfoResolver.getContextualType(objectLiteral);
|
||||
var name = (<Identifier>node).text;
|
||||
if (contextualType) {
|
||||
return typeInfoResolver.getPropertyOfType(contextualType, (<Identifier>node).text);
|
||||
if (contextualType.flags & TypeFlags.Union) {
|
||||
// This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types)
|
||||
// if not, search the constituent types for the property
|
||||
var unionProperty = contextualType.getProperty(name)
|
||||
if (unionProperty) {
|
||||
return [unionProperty];
|
||||
}
|
||||
else {
|
||||
var result: Symbol[] = [];
|
||||
forEach((<UnionType>contextualType).types, t => {
|
||||
var symbol = t.getProperty(name);
|
||||
if (symbol) {
|
||||
result.push(symbol);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var symbol = contextualType.getProperty(name);
|
||||
if (symbol) {
|
||||
return [symbol];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
20
tests/cases/fourslash/completionEntryForUnionProperty.ts
Normal file
20
tests/cases/fourslash/completionEntryForUnionProperty.ts
Normal file
@ -0,0 +1,20 @@
|
||||
///<reference path="fourslash.ts" />
|
||||
|
||||
////interface One {
|
||||
//// commonProperty: number;
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////interface Two {
|
||||
//// commonProperty: string
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////var x : One | Two;
|
||||
////
|
||||
////x./**/
|
||||
|
||||
goTo.marker();
|
||||
verify.memberListContains("commonProperty", "string | number", undefined, undefined, "property");
|
||||
verify.memberListContains("commonFunction", "() => number", undefined, undefined, "method");
|
||||
verify.memberListCount(2);
|
||||
19
tests/cases/fourslash/completionEntryForUnionProperty2.ts
Normal file
19
tests/cases/fourslash/completionEntryForUnionProperty2.ts
Normal file
@ -0,0 +1,19 @@
|
||||
///<reference path="fourslash.ts" />
|
||||
|
||||
////interface One {
|
||||
//// commonProperty: number;
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////interface Two {
|
||||
//// commonProperty: string
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////var x : One | Two;
|
||||
////
|
||||
////x.commonProperty./**/
|
||||
|
||||
goTo.marker();
|
||||
verify.memberListContains("toString", "() => string", undefined, undefined, "method");
|
||||
verify.memberListCount(1);
|
||||
24
tests/cases/fourslash/goToDefinitionUnionTypeProperty.ts
Normal file
24
tests/cases/fourslash/goToDefinitionUnionTypeProperty.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////interface One {
|
||||
//// /*propertyDefinition1*/commonProperty: number;
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////interface Two {
|
||||
//// /*propertyDefinition2*/commonProperty: string
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////var x : One | Two;
|
||||
////
|
||||
////x./*propertyReference*/commonProperty;
|
||||
////x./*3*/commonFunction;
|
||||
|
||||
goTo.marker("propertyReference");
|
||||
goTo.definition(0);
|
||||
verify.caretAtMarker("propertyDefinition1");
|
||||
|
||||
goTo.marker("propertyReference");
|
||||
goTo.definition(1);
|
||||
verify.caretAtMarker("propertyDefinition2");
|
||||
25
tests/cases/fourslash/goToDefinitionUnionTypeProperty2.ts
Normal file
25
tests/cases/fourslash/goToDefinitionUnionTypeProperty2.ts
Normal file
@ -0,0 +1,25 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
////interface HasAOrB {
|
||||
//// /*propertyDefinition1*/a: string;
|
||||
//// b: string;
|
||||
////}
|
||||
////
|
||||
////interface One {
|
||||
//// common: { /*propertyDefinition2*/a : number; };
|
||||
////}
|
||||
////
|
||||
////interface Two {
|
||||
//// common: HasAOrB;
|
||||
////}
|
||||
////
|
||||
////var x : One | Two;
|
||||
////
|
||||
////x.common./*propertyReference*/a;
|
||||
|
||||
goTo.marker("propertyReference");
|
||||
goTo.definition(0);
|
||||
verify.caretAtMarker("propertyDefinition1");
|
||||
|
||||
goTo.marker("propertyReference");
|
||||
goTo.definition(1);
|
||||
verify.caretAtMarker("propertyDefinition2");
|
||||
27
tests/cases/fourslash/quickinfoForUnionProperty.ts
Normal file
27
tests/cases/fourslash/quickinfoForUnionProperty.ts
Normal file
@ -0,0 +1,27 @@
|
||||
/// <reference path="fourslash.ts"/>
|
||||
|
||||
////interface One {
|
||||
//// commonProperty: number;
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////interface Two {
|
||||
//// commonProperty: string
|
||||
//// commonFunction(): number;
|
||||
////}
|
||||
////
|
||||
////var /*1*/x : One | Two;
|
||||
////
|
||||
////x./*2*/commonProperty;
|
||||
////x./*3*/commonFunction;
|
||||
|
||||
|
||||
goTo.marker("1");
|
||||
verify.quickInfoIs("One | Two", "", "x", "var");
|
||||
|
||||
|
||||
goTo.marker("2");
|
||||
verify.quickInfoIs("string | number", "", "commonProperty", "property");
|
||||
|
||||
goTo.marker("3");
|
||||
verify.quickInfoIs("() => number", "", "commonFunction", "method");
|
||||
@ -1,5 +1,5 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface IFoo { /*1*/xy: number; }
|
||||
////
|
||||
////// Assignment
|
||||
@ -23,10 +23,10 @@
|
||||
////var w: IFoo = { /*4*/xy: undefined };
|
||||
////
|
||||
////// Untped -- should not be included
|
||||
////var u = { xy: 0 };
|
||||
|
||||
|
||||
test.markers().forEach((m) => {
|
||||
goTo.position(m.position, m.fileName);
|
||||
verify.referencesCountIs(9);
|
||||
});
|
||||
////var u = { xy: 0 };
|
||||
|
||||
|
||||
test.markers().forEach((m) => {
|
||||
goTo.position(m.position, m.fileName);
|
||||
verify.referencesCountIs(9);
|
||||
});
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface A {
|
||||
//// a: number;
|
||||
//// common: string;
|
||||
////}
|
||||
////
|
||||
////interface B {
|
||||
//// b: number;
|
||||
//// common: number;
|
||||
////}
|
||||
////
|
||||
////// Assignment
|
||||
////var v1: A | B = { a: 0, /*1*/common: "" };
|
||||
////var v2: A | B = { b: 0, /*2*/common: 3 };
|
||||
////
|
||||
////// Function call
|
||||
////function consumer(f: A | B) { }
|
||||
////consumer({ a: 0, b: 0, /*3*/common: 1 });
|
||||
////
|
||||
////// Type cast
|
||||
////var c = <A | B> { /*4*/common: 0, b: 0 };
|
||||
////
|
||||
////// Array literal
|
||||
////var ar: Array<A|B> = [{ a: 0, /*5*/common: "" }, { b: 0, /*6*/common: 0 }];
|
||||
////
|
||||
////// Nested object literal
|
||||
////var ob: { aorb: A|B } = { aorb: { b: 0, /*7*/common: 0 } };
|
||||
////
|
||||
////// Widened type
|
||||
////var w: A|B = { a:0, /*8*/common: undefined };
|
||||
////
|
||||
////// Untped -- should not be included
|
||||
////var u1 = { a: 0, b: 0, common: "" };
|
||||
////var u2 = { b: 0, common: 0 };
|
||||
|
||||
test.markers().forEach((m) => {
|
||||
goTo.position(m.position, m.fileName);
|
||||
verify.referencesCountIs(10); // 8 contextually typed common, and 2 in definition (A.common, B.common)
|
||||
});
|
||||
@ -0,0 +1,40 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface A {
|
||||
//// a: number;
|
||||
//// common: string;
|
||||
////}
|
||||
////
|
||||
////interface B {
|
||||
//// /*1*/b: number;
|
||||
//// common: number;
|
||||
////}
|
||||
////
|
||||
////// Assignment
|
||||
////var v1: A | B = { a: 0, common: "" };
|
||||
////var v2: A | B = { /*2*/b: 0, common: 3 };
|
||||
////
|
||||
////// Function call
|
||||
////function consumer(f: A | B) { }
|
||||
////consumer({ a: 0, /*3*/b: 0, common: 1 });
|
||||
////
|
||||
////// Type cast
|
||||
////var c = <A | B> { common: 0, /*4*/b: 0 };
|
||||
////
|
||||
////// Array literal
|
||||
////var ar: Array<A|B> = [{ a: 0, common: "" }, { /*5*/b: 0, common: 0 }];
|
||||
////
|
||||
////// Nested object literal
|
||||
////var ob: { aorb: A|B } = { aorb: { /*6*/b: 0, common: 0 } };
|
||||
////
|
||||
////// Widened type
|
||||
////var w: A|B = { /*7*/b:undefined, common: undefined };
|
||||
////
|
||||
////// Untped -- should not be included
|
||||
////var u1 = { a: 0, b: 0, common: "" };
|
||||
////var u2 = { b: 0, common: 0 };
|
||||
|
||||
test.markers().forEach((m) => {
|
||||
goTo.position(m.position, m.fileName);
|
||||
verify.referencesCountIs(7);
|
||||
});
|
||||
35
tests/cases/fourslash/referencesForUnionProperties.ts
Normal file
35
tests/cases/fourslash/referencesForUnionProperties.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface One {
|
||||
//// common: { /*1*/a: number; };
|
||||
////}
|
||||
////
|
||||
////interface Base {
|
||||
//// /*2*/a: string;
|
||||
//// b: string;
|
||||
////}
|
||||
////
|
||||
////interface HasAOrB extends Base {
|
||||
//// /*3*/a: string;
|
||||
//// b: string;
|
||||
////}
|
||||
////
|
||||
////interface Two {
|
||||
//// common: HasAOrB;
|
||||
////}
|
||||
////
|
||||
////var x : One | Two;
|
||||
////
|
||||
////x.common./*4*/a;
|
||||
|
||||
goTo.marker("1");
|
||||
verify.referencesCountIs(2); // One.common.a, x.common.a
|
||||
|
||||
goTo.marker("2");
|
||||
verify.referencesCountIs(3); // Base.a, HasAOrB.a, x.common.a
|
||||
|
||||
goTo.marker("3");
|
||||
verify.referencesCountIs(3); // Base.a, HasAOrB.a, x.common.a
|
||||
|
||||
goTo.marker("4");
|
||||
verify.referencesCountIs(4); // One.common.a, Base.a, HasAOrB.a, x.common.a
|
||||
Loading…
x
Reference in New Issue
Block a user