Skip to content
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

Adds support for type parameter defaults #13487

Merged
merged 23 commits into from
Feb 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3d3dae0
Adds support for type parameter defaults
rbuckton Jan 14, 2017
442f540
Updated Promise and PromiseLike to use defaults
rbuckton Jan 14, 2017
25cb02e
Fix circularity check, simplify default type mapper
rbuckton Jan 14, 2017
ca16ba8
Added comments and additional circularity tests
rbuckton Jan 14, 2017
0b44a2c
Flexible declaration merging
rbuckton Jan 19, 2017
0500065
Avoid inference for fully-supplied type arguments
rbuckton Jan 20, 2017
5ff0f81
Diagnostic message punctuation
rbuckton Jan 20, 2017
a2be5e2
Report error using type parameter from merged declaration
rbuckton Jan 21, 2017
fd228a9
Remove partial inference
rbuckton Jan 21, 2017
6b2c8cb
Defaults for type aliases
rbuckton Jan 21, 2017
76ba6a7
Merge branch 'master' into genericDefaults
rbuckton Jan 21, 2017
15232fe
Remove circular default check
rbuckton Jan 24, 2017
f5f1c7e
Merge branch 'genericDefaults' of https://github.com/Microsoft/TypeSc…
rbuckton Jan 24, 2017
febde3f
Revert noConstraintType name change
rbuckton Jan 24, 2017
b58ef9e
Merge branch 'master' into genericDefaults
rbuckton Jan 30, 2017
7616e37
Use length() throught checker
rbuckton Jan 30, 2017
e001258
Move non-local type parameter check to resolveName
rbuckton Jan 30, 2017
9ba2a6b
Skip type parameters.
rbuckton Feb 1, 2017
6091050
Remove pre-computation of minTypeArgumentCount
rbuckton Feb 3, 2017
6ffcbf5
Merge branch 'master' into genericDefaults
rbuckton Feb 3, 2017
5bb2fe0
Simplify checkTypeParameterListsIdentical
rbuckton Feb 4, 2017
96181c0
Shortcut for class/namespace merge
rbuckton Feb 4, 2017
23216f9
Merge branch 'master' into genericDefaults
rbuckton Feb 15, 2017
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
313 changes: 246 additions & 67 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions src/compiler/declarationEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,23 @@ namespace ts {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError);
}
}
if (node.default && !isPrivateMethodTypeParameter(node)) {
write(" = ");
if (node.parent.kind === SyntaxKind.FunctionType ||
node.parent.kind === SyntaxKind.ConstructorType ||
(node.parent.parent && node.parent.parent.kind === SyntaxKind.TypeLiteral)) {
Debug.assert(node.parent.kind === SyntaxKind.MethodDeclaration ||
node.parent.kind === SyntaxKind.MethodSignature ||
node.parent.kind === SyntaxKind.FunctionType ||
node.parent.kind === SyntaxKind.ConstructorType ||
node.parent.kind === SyntaxKind.CallSignature ||
node.parent.kind === SyntaxKind.ConstructSignature);
emitType(node.default);
}
else {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.default, getTypeParameterConstraintVisibilityError);
}
}

function getTypeParameterConstraintVisibilityError(): SymbolAccessibilityDiagnostic {
// Type parameter constraints are named by user so we should always be able to name it
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2059,6 +2059,14 @@
"category": "Error",
"code": 2705
},
"Required type parameters may not follow optional type parameters.": {
"category": "Error",
"code": 2706
},
"Generic type '{0}' requires between {1} and {2} type arguments.": {
"category": "Error",
"code": 2707
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ namespace ts {
case SyntaxKind.TypeParameter:
return visitNode(cbNode, (<TypeParameterDeclaration>node).name) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).constraint) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).default) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
case SyntaxKind.ShorthandPropertyAssignment:
return visitNodes(cbNodes, node.decorators) ||
Expand Down Expand Up @@ -2102,6 +2103,10 @@ namespace ts {
}
}

if (parseOptional(SyntaxKind.EqualsToken)) {
node.default = parseType();
}
Copy link
Member

@DanielRosenwasser DanielRosenwasser Jan 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I would really like for if the parsing was order-agnostic for the purpose of error reporting, and then gave a grammar error later on. This could be done as a separate pass.


return finishNode(node);
}

Expand Down
5 changes: 5 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@
kind: SyntaxKind.TypeParameter;
name: Identifier;
constraint?: TypeNode;
default?: TypeNode;

// For error recovery purposes.
expression?: Expression;
Expand Down Expand Up @@ -2736,6 +2737,7 @@
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
resolvedExports?: SymbolTable; // Resolved exports of module
exportsChecked?: boolean; // True if exports of external module have been checked
typeParametersChecked?: boolean; // True if type parameters of merged class and interface declarations have been checked.
isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration
bindingElement?: BindingElement; // Binding element associated with property symbol
exportsSomeValue?: boolean; // True if module exports some value (not just types)
Expand Down Expand Up @@ -3060,12 +3062,15 @@
// Type parameters (TypeFlags.TypeParameter)
export interface TypeParameter extends TypeVariable {
constraint: Type; // Constraint
default?: Type;
/* @internal */
target?: TypeParameter; // Instantiation target
/* @internal */
mapper?: TypeMapper; // Instantiation mapper
/* @internal */
isThisType?: boolean;
/* @internal */
resolvedDefaultType?: Type;
}

// Indexed access types (TypeFlags.IndexedAccess)
Expand Down
14 changes: 14 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ namespace ts {
return undefined;
}

export function findDeclaration<T extends Declaration>(symbol: Symbol, predicate: (node: Declaration) => node is T): T | undefined;
export function findDeclaration(symbol: Symbol, predicate: (node: Declaration) => boolean): Declaration | undefined;
export function findDeclaration(symbol: Symbol, predicate: (node: Declaration) => boolean): Declaration | undefined {
const declarations = symbol.declarations;
if (declarations) {
for (const declaration of declarations) {
if (predicate(declaration)) {
return declaration;
}
}
}
return undefined;
}

export interface StringSymbolWriter extends SymbolWriter {
string(): string;
}
Expand Down
1 change: 0 additions & 1 deletion src/lib/es2015.promise.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

interface PromiseConstructor {
/**
* A reference to the prototype.
Expand Down
69 changes: 3 additions & 66 deletions src/lib/es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1310,39 +1310,7 @@ interface PromiseLike<T> {
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then(
onfulfilled?: ((value: T) => T | PromiseLike<T>) | undefined | null,
onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): PromiseLike<T>;

/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(
onfulfilled: ((value: T) => T | PromiseLike<T>) | undefined | null,
onrejected: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<T | TResult>;

/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(
onfulfilled: (value: T) => TResult | PromiseLike<TResult>,
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): PromiseLike<TResult>;

/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1, TResult2>(
onfulfilled: (value: T) => TResult1 | PromiseLike<TResult1>,
onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>;
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
}

/**
Expand All @@ -1355,45 +1323,14 @@ interface Promise<T> {
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then(onfulfilled?: ((value: T) => T | PromiseLike<T>) | undefined | null, onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): Promise<T>;

/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled: ((value: T) => T | PromiseLike<T>) | undefined | null, onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<T | TResult>;

/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled: (value: T) => TResult | PromiseLike<TResult>, onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<TResult>;

/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1, TResult2>(onfulfilled: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): Promise<TResult1 | TResult2>;

/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch(onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): Promise<T>;
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;

/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult>(onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<T | TResult>;
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
}

interface ArrayLike<T> {
Expand Down
1 change: 1 addition & 0 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ namespace ts {
parameters: Symbol[];
thisParameter: Symbol;
resolvedReturnType: Type;
minTypeArgumentCount: number;
minArgumentCount: number;
hasRestParameter: boolean;
hasLiteralTypes: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
Types of property 'then' are incompatible.
Type '() => void' is not assignable to type '{ (onfulfilled?: (value: any) => any, onrejected?: (reason: any) => any): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => any, onrejected: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult1, TResult2>(onfulfilled: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; }'.
Type '() => void' is not assignable to type '<TResult1 = any, TResult2 = never>(onfulfilled?: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<TResult1 | TResult2>'.
Type 'void' is not assignable to type 'PromiseLike<any>'.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(17,16): error TS1059: Return expression in async function does not have a valid callable 'then' member.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(23,25): error TS1058: Operand for 'await' does not have a valid callable 'then' member.
Expand Down Expand Up @@ -37,7 +37,7 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
!!! error TS1055: Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
!!! error TS1055: Types of property 'then' are incompatible.
!!! error TS1055: Type '() => void' is not assignable to type '{ (onfulfilled?: (value: any) => any, onrejected?: (reason: any) => any): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => any, onrejected: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult1, TResult2>(onfulfilled: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; }'.
!!! error TS1055: Type '() => void' is not assignable to type '<TResult1 = any, TResult2 = never>(onfulfilled?: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<TResult1 | TResult2>'.
!!! error TS1055: Type 'void' is not assignable to type 'PromiseLike<any>'.
async function fn7() { return; } // valid: Promise<void>
async function fn8() { return 1; } // valid: Promise<number>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
tests/cases/conformance/types/objectTypeLiteral/constructSignatures/constructSignaturesWithOverloads2.ts(27,11): error TS2428: All declarations of 'I' must have identical type parameters.
tests/cases/conformance/types/objectTypeLiteral/constructSignatures/constructSignaturesWithOverloads2.ts(32,11): error TS2428: All declarations of 'I' must have identical type parameters.


==== tests/cases/conformance/types/objectTypeLiteral/constructSignatures/constructSignaturesWithOverloads2.ts (1 errors) ====
==== tests/cases/conformance/types/objectTypeLiteral/constructSignatures/constructSignaturesWithOverloads2.ts (2 errors) ====
// No errors expected for basic overloads of construct signatures with merged declarations

// clodules
Expand Down Expand Up @@ -29,6 +30,8 @@ tests/cases/conformance/types/objectTypeLiteral/constructSignatures/constructSig

// merged interfaces
interface I {
~
!!! error TS2428: All declarations of 'I' must have identical type parameters.
new (x: number, y?: string): C;
new (x: number, y: string): C;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
tests/cases/compiler/extendedInterfacesWithDuplicateTypeParameters.ts(1,42): error TS2300: Duplicate identifier 'A'.
tests/cases/compiler/extendedInterfacesWithDuplicateTypeParameters.ts(5,11): error TS2428: All declarations of 'InterfaceWithSomeTypars' must have identical type parameters.
tests/cases/compiler/extendedInterfacesWithDuplicateTypeParameters.ts(9,11): error TS2428: All declarations of 'InterfaceWithSomeTypars' must have identical type parameters.
tests/cases/compiler/extendedInterfacesWithDuplicateTypeParameters.ts(9,38): error TS2300: Duplicate identifier 'C'.


==== tests/cases/compiler/extendedInterfacesWithDuplicateTypeParameters.ts (3 errors) ====
==== tests/cases/compiler/extendedInterfacesWithDuplicateTypeParameters.ts (4 errors) ====
interface InterfaceWithMultipleTypars<A, A> { // should error
~
!!! error TS2300: Duplicate identifier 'A'.
bar(): void;
}

interface InterfaceWithSomeTypars<B> { // should not error
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2428: All declarations of 'InterfaceWithSomeTypars' must have identical type parameters.
bar(): void;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterfaceWithTheSameName.ts(3,11): error TS2428: All declarations of 'A' must have identical type parameters.
tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterfaceWithTheSameName.ts(7,11): error TS2428: All declarations of 'A' must have identical type parameters.
tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterfaceWithTheSameName.ts(12,15): error TS2428: All declarations of 'A' must have identical type parameters.
tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterfaceWithTheSameName.ts(16,15): error TS2428: All declarations of 'A' must have identical type parameters.
tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterfaceWithTheSameName.ts(34,22): error TS2428: All declarations of 'A' must have identical type parameters.
tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterfaceWithTheSameName.ts(40,22): error TS2428: All declarations of 'A' must have identical type parameters.


==== tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterfaceWithTheSameName.ts (3 errors) ====
==== tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterfaceWithTheSameName.ts (6 errors) ====
// generic and non-generic interfaces with the same name do not merge

interface A {
~
!!! error TS2428: All declarations of 'A' must have identical type parameters.
foo: string;
}

Expand All @@ -18,6 +23,8 @@ tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterf

module M {
interface A<T> {
~
!!! error TS2428: All declarations of 'A' must have identical type parameters.
bar: T;
}

Expand All @@ -42,6 +49,8 @@ tests/cases/conformance/interfaces/declarationMerging/genericAndNonGenericInterf

module M3 {
export interface A {
~
!!! error TS2428: All declarations of 'A' must have identical type parameters.
foo: string;
}
}
Expand Down
Loading