8000 Union Types by ahejlsberg · Pull Request #824 · microsoft/TypeScript · GitHub
[go: up one dir, main page]

Skip to content

Union Types #824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Oct 13, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e836fe1
Initial implementation of Union Types
ahejlsberg Oct 4, 2014
d70494f
Narrowing of variable types using typeof/instanceof type guards
ahejlsberg Oct 7, 2014
b8923b3
Support symbol kind for union properties
mhegazy Oct 8, 2014
5669f63
add test for quick info
mhegazy Oct 8, 2014
c439ae4
Add support for union properties in goto def
mhegazy Oct 8, 2014
95584e9
Addressing CR feedback
ahejlsberg Oct 8, 2014
fd5b808
Accepting new baselines
ahejlsberg Oct 8, 2014
3a17b02
Improved type argument inference with union types
ahejlsberg Oct 8, 2014
ea4cbbe
Merge branch 'master' into unionTypes
ahejlsberg Oct 8, 2014
5c661ba
Accepting new baselines after merge with master
ahejlsberg Oct 8, 2014
779db6e
Support find all refs on union properties
mhegazy Oct 9, 2014
2eb51ab
Use getRootSymbols for all union property needs
mhegazy Oct 9, 2014
dc43e83
Merge branch 'unionTypes' into unionTypesLS
mhegazy Oct 9, 2014
927f04f
Fix contextually typed object literal proeprties that are not propert…
mhegazy Oct 9, 2014
9f43ac0
respond to code review remarks
mhegazy Oct 10, 2014
bacb9d0
Test updates from union changes
danquirk Oct 10, 2014
8ce1760
Fixing merge conflicts
danquirk Oct 10, 2014
f5a9fee
ensure unionProperty symbols have declarations set at creation time
mhegazy Oct 10, 2014
483afea
Less aggressive subtype reduction in union types
ahejlsberg Oct 10, 2014
4e02b9f
Merge branch 'unionTypes' of https://github.com/Microsoft/TypeScript …
ahejlsberg Oct 10, 2014
c9a42c1
Accepting new baselines
ahejlsberg Oct 11, 2014
2ce627c
Handle union properties completions on apparant types
mhegazy Oct 11, 2014
4442b45
Add a temporary fix to quick info
mhegazy Oct 11, 2014
04e5309
Merge branch 'unionTypes' into unionTypesLS
mhegazy Oct 11, 2014
eee1602
Merge pull request #861 from Microsoft/unionTypesLS
mhegazy Oct 11, 2014
83d9aed
Correct contextual typing with union types
ahejlsberg Oct 13, 2014
a76a418
Accepting new baselines
ahejlsberg Oct 13, 2014
869ee41
Addressing CR feedback
ahejlsberg Oct 13, 2014
fc842b1
Merge branch 'master' into unionTypes
ahejlsberg Oct 13, 2014
4f4f59a
Merge changes from master in services.ts
mhegazy Oct 13, 2014
f5cd414
Merge branch 'master' into unionTypes
mhegazy Oct 13, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge changes from master in services.ts
  • Loading branch information
mhegazy committed Oct 13, 2014
commit 4f4f59a78165dfec2cfcb57cd823009840597315
1 change: 0 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ module ts {
symbolToString: symbolToString,
writeSymbol: writeSymbol,
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType,
getRootSymbol: getRootSymbol,
getRootSymbols: getRootSymbols,
getContextualType: getContextualType,
getFullyQualifiedName: getFullyQualifiedName,
Expand Down
1 change: 0 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,6 @@ module ts {
writeSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
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;
Expand Down
68 changes: 25 additions & 43 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2259,9 +2259,13 @@ module ts {
return undefined;
}

// TODO(drosen): Right now we just permit *all* semantic meanings when calling 'getSymbolKind'
// which is permissible given that it is backwards compatible; but really we should consider
// passing the meaning for the node so that we don't report that a suggestion for a value is an interface.
// We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration.
return {
name: displayName,
kind: getSymbolKind(symbol),
kind: getSymbolKind(symbol, SemanticMeaning.All),
kindModifiers: getSymbolModifiers(symbol)
};
}
Expand Down Expand Up @@ -2613,7 +2617,7 @@ module ts {
// which is permissible given that it is backwards compatible; but really we should consider
// passing the meaning for the node so that we don't report that a suggestion for a value is an interface.
// We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration.
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), session.location, session.typeChecker, session.location);
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), session.location, session.typeChecker, session.location, SemanticMeaning.All);
return {
name: entryName,
kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
Expand Down Expand Up @@ -2656,15 +2660,19 @@ module ts {
}
}

// TODO(drosen): use contextual SemanticMeaning.
function getSymbolKind(symbol: Symbol): string {
function getSymbolKind(symbol: Symbol, meaningAtLocation: SemanticMeaning): string {
var flags = typeInfoResolver.getRootSymbols(symbol)[0].getFlags();

if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;


// The following should only apply if encountered at a type position,
// and need to have precedence over other meanings if this is the case.
if (meaningAtLocation & SemanticMeaning.Type) {
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
}

var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags);
if (result === ScriptElementKind.unknown) {
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
Expand Down Expand Up @@ -2737,15 +2745,13 @@ module ts {
: ScriptElementKindModifier.none;
}

// TODO(drosen): use contextual SemanticMeaning.
function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol,
sourceFile: SourceFile,
enclosingDeclaration: Node,
typeResolver: TypeChecker,
location: Node) {
function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node,
typeResolver: TypeChecker, location: Node,
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
semanticMeaning = getMeaningFromLocation(location)) {
var displayParts: SymbolDisplayPart[] = [];
var documentation: SymbolDisplayPart[];
var symbolFlags = typeResolver.getRootSymbol(symbol).flags;
var symbolFlags = typeResolver.getRootSymbols(symbol)[0].flags;
var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags);
var hasAddedSymbolInfo: boolean;
// Class at constructor site need to be shown as constructor apart from property,method, vars
Expand Down Expand Up @@ -2847,14 +2853,13 @@ module ts {
}
}
}

if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo) {
displayParts.push(keywordPart(SyntaxKind.ClassKeyword));
displayParts.push(spacePart());
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments));
writeTypeParametersOfSymbol(symbol, sourceFile);
}
if (symbolFlags & SymbolFlags.Interface) {
if ((symbolFlags & SymbolFlags.Interface) && (semanticMeaning & SemanticMeaning.Type)) {
addNewLineIfDisplayPartsExist();
displayParts.push(keywordPart(SyntaxKind.InterfaceKeyword));
displayParts.push(spacePart());
Expand All @@ -2873,7 +2878,7 @@ module ts {
displayParts.push(spacePart());
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile));
}
if (symbolFlags & SymbolFlags.TypeParameter) {
if ((symbolFlags & SymbolFlags.TypeParameter) && (semanticMeaning & SemanticMeaning.Type)) {
addNewLineIfDisplayPartsExist();
displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
displayParts.push(textPart("type parameter"));
Expand Down Expand Up @@ -2953,7 +2958,7 @@ module ts {
}
}
else {
symbolKind = getSymbolKind(symbol);
symbolKind = getSymbolKind(symbol, semanticMeaning);
}
}

Expand Down Expand Up @@ -3015,7 +3020,6 @@ module ts {

var symbol = typeInfoResolver.getSymbolInfo(node);
if (!symbol) {

// Try getting just type at this position and show
switch (node.kind) {
case SyntaxKind.Identifier:
Expand Down Expand Up @@ -3107,25 +3111,6 @@ 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);
Expand Down Expand Up @@ -3173,7 +3158,7 @@ module ts {

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 symbolKind = getSymbolKind(symbol, getMeaningFromLocation(node));
var containerSymbol = symbol.parent;
var containerName = containerSymbol ? typeInfoResolver.symbolToString(containerSymbol, node) : "";

Expand Down Expand Up @@ -4703,7 +4688,6 @@ module ts {
function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning) {
var flags = symbol.getFlags();

// TODO(drosen): use meaningAtPosition.
if (flags & SymbolFlags.Class) {
return ClassificationTypeNames.className;
}
Expand All @@ -4721,8 +4705,6 @@ module ts {
else if (flags & SymbolFlags.Module) {
return ClassificationTypeNames.moduleName;
}

return undefined;
}

function processNode(node: Node) {
Expand Down Expand Up @@ -5192,7 +5174,7 @@ module ts {

// Only allow a symbol to be renamed if it actually has at least one declaration.
if (symbol && symbol.getDeclarations() && symbol.getDeclarations().length > 0) {
var kind = getSymbolKind(symbol);
var kind = getSymbolKind(symbol, getMeaningFromLocation(node));
if (kind) {
return getRenameInfo(symbol.name, typeInfoResolver.getFullyQualifiedName(symbol), kind,
getSymbolModifiers(symbol),
Expand Down
13 changes: 11 additions & 2 deletions tests/cases/fourslash/bestCommonTypeObjectLiterals1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,19 @@ goTo.marker('2');
verify.quickInfoIs('(var) c1: {\n name: string;\n age: number;\n}[]');

goTo.marker('3');
verify.quickInfoIs('(var) c2: {}[]');
verify.quickInfoIs('(var) c2: Array<{\n\
name: string;\n\
age: number;\n\
address: string;\n\
} | {\n\
name: string;\n\
age: number;\n\
dob: Date;\n\
}>');

goTo.marker('4');
verify.quickInfoIs('(var) c2a: {\n name: string;\n age: number;\n}[]');

goTo.marker('5');
verify.quickInfoIs('(var) c3: I[]');
verify.quickInfoIs('(var) c3: I[]');

4 changes: 2 additions & 2 deletions tests/cases/fourslash/completionEntryForUnionProperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
////x./**/

goTo.marker();
verify.memberListContains("commonProperty", "string | number", undefined, undefined, "property");
verify.memberListContains("commonFunction", "() => number", undefined, undefined, "method");
verify.memberListContains("commonProperty", "(property) commonProperty: string | number");
verify.memberListContains("commonFunction", "(method) commonFunction(): number");
verify.memberListCount(2);
2 changes: 1 addition & 1 deletion tests/cases/fourslash/completionEntryForUnionProperty2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
////x.commonProperty./**/

goTo.marker();
verify.memberListContains("toString", "() => string", undefined, undefined, "method");
verify.memberListContains("toString", "(method) toString(): string");
verify.memberListCount(1);
4 changes: 2 additions & 2 deletions tests/cases/fourslash/contextualTypingOfArrayLiterals1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ goTo.marker('4');
verify.quickInfoIs('(var) r4: C');

goTo.marker('5');
verify.quickInfoIs('(var) x5: {\n name: string;\n age: number;\n}[]');
verify.quickInfoIs('(var) x5: C[]');

goTo.marker('6');
verify.quickInfoIs('(var) r5: {\n name: string;\n age: number;\n}');
verify.quickInfoIs('(var) r5: C');
6 changes: 3 additions & 3 deletions tests/cases/fourslash/genericTypeArgumentInference1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
////var /*4*/r4 = _./*41*/all([<any>true], _.identity);

goTo.marker('1');
verify.quickInfoIs('(var) r: {}');
verify.quickInfoIs('(var) r: string | number | boolean');
goTo.marker('11');
verify.quickInfoIs('(method) Underscore.Static.all<{}>(list: {}[], iterator?: Underscore.Iterator<{}, boolean>, context?: any): {}');
verify.quickInfoIs('(method) Underscore.Static.all<string | number | boolean>(list: Array<string | number | boolean>, iterator?: Underscore.Iterator<string | number | boolean, boolean>, context?: any): string | number | boolean');

goTo.marker('2');
verify.quickInfoIs('(var) r2: boolean');
Expand All @@ -37,4 +37,4 @@ verify.quickInfoIs('(var) r4: any');
goTo.marker('41');
verify.quickInfoIs('(method) Underscore.Static.all<any>(list: any[], iterator?: Underscore.Iterator<any, boolean>, context?: any): any');

verify.numberOfErrorsInCurrentFile(0);
verify.numberOfErrorsInCurrentFile(0);
4 changes: 2 additions & 2 deletions tests/cases/fourslash/genericTypeArgumentInference2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
////var /*4*/r4 = _./*41*/all([<any>true], _.identity);

goTo.marker('1');
verify.quickInfoIs('(var) r: {}');
verify.quickInfoIs('(var) r: string | number | boolean');
goTo.marker('11');
verify.quickInfoIs('(method) Underscore.Static.all<{}>(list: {}[], iterator?: Underscore.Iterator<{}, boolean>, context?: any): {}');
verify.quickInfoIs('(method) Underscore.Static.all<string | number | boolean>(list: Array<string | number | boolean>, iterator?: Underscore.Iterator<string | number | boolean, boolean>, context?: any): string | number | boolean');

goTo.marker('2');
verify.quickInfoIs('(var) r2: boolean');
Expand Down
6 changes: 3 additions & 3 deletions tests/cases/fourslash/quickinfoForUnionProperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@


goTo.marker("1");
verify.quickInfoIs("One | Two", "", "x", "var");
verify.quickInfoIs('(var) x: One | Two');


goTo.marker("2");
verify.quickInfoIs("string | number", "", "commonProperty", "property");
verify.quickInfoIs('(property) commonProperty: string | number');

goTo.marker("3");
verify.quickInfoIs("() => number", "", "commonFunction", "method");
verify.quickInfoIs('(method) commonFunction(): number');
0