-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Review PR: Abstract classes #2946
Changes from 3 commits
d4e97ae
dc7d9cf
651658d
30bdb52
42f197a
48fa9f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1447,6 +1447,10 @@ | |
"category": "Error", | ||
"code": 2501 | ||
}, | ||
"Cannot create an instance of the abstract class '{1}'": { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "cannot use @JsonFreeman may have better message though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oke, Will change this (but I will wait for feedback from JsonFreeman) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why 1, and not 0 (for the substitution slot)? I think I like the "Cannot create an instance" message better. |
||
"category": "Error", | ||
"code": 2501 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Codes should be distinct |
||
}, | ||
|
||
"Import declaration '{0}' is using private name '{1}'.": { | ||
"category": "Error", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -128,6 +128,7 @@ module ts { | |
PrivateKeyword, | ||
ProtectedKeyword, | ||
PublicKeyword, | ||
AbstractKeyword, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not a future reserved word in ES6, should move to the contextual keywords block. you should also add a test for variables named "abstract" with "use strict"; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Jup will do, didn't wrote a (full) test-suite yet because I wanted to know if the code was a bit in the right places |
||
StaticKeyword, | ||
YieldKeyword, | ||
// Contextual keywords | ||
|
@@ -307,15 +308,16 @@ module ts { | |
Protected = 0x00000040, // Property/Method | ||
Static = 0x00000080, // Property/Method | ||
Default = 0x00000100, // Function/Class (export default declaration) | ||
MultiLine = 0x00000200, // Multi-line array or object literal | ||
Synthetic = 0x00000400, // Synthetic node (for full fidelity) | ||
DeclarationFile = 0x00000800, // Node is a .d.ts file | ||
Let = 0x00001000, // Variable declaration | ||
Const = 0x00002000, // Variable declaration | ||
OctalLiteral = 0x00004000, | ||
ExportContext = 0x00008000, // Export context (initialized by binding) | ||
|
||
Modifier = Export | Ambient | Public | Private | Protected | Static | Default, | ||
Abstract = 0x00000200, | ||
MultiLine = 0x00000400, // Multi-line array or object literal | ||
Synthetic = 0x00000800, // Synthetic node (for full fidelity) | ||
DeclarationFile = 0x00001000, // Node is a .d.ts file | ||
Let = 0x00002000, // Variable declaration | ||
Const = 0x00004000, // Variable declaration | ||
OctalLiteral = 0x00008000, | ||
ExportContext = 0x00010000, // Export context (initialized by binding) | ||
|
||
Modifier = Export | Ambient | Public | Private | Protected | Static | Default | Abstract, | ||
AccessibilityModifier = Public | Private | Protected, | ||
BlockScoped = Let | Const | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
tests/cases/compiler/abstractClass1.ts(15,9): error TS2501: Cannot create an instance of the abstract class 'undefined' | ||
tests/cases/compiler/abstractClass1.ts(16,9): error TS2346: Supplied parameters do not match any signature of call target. | ||
tests/cases/compiler/abstractClass1.ts(16,9): error TS2501: Cannot create an instance of the abstract class 'undefined' | ||
tests/cases/compiler/abstractClass1.ts(28,1): error TS2346: Supplied parameters do not match any signature of call target. | ||
tests/cases/compiler/abstractClass1.ts(28,1): error TS2501: Cannot create an instance of the abstract class 'undefined' | ||
|
||
|
||
==== tests/cases/compiler/abstractClass1.ts (5 errors) ==== | ||
|
||
abstract class Foo { | ||
constructor(f: any) { } | ||
public static bar(): void { } | ||
|
||
public empty() { } | ||
} | ||
|
||
class Bar extends Foo { | ||
constructor(f: any) { | ||
super(f); | ||
} | ||
} | ||
|
||
var a = new Foo(1); // Error | ||
~~~~~~~~~~ | ||
!!! error TS2501: Cannot create an instance of the abstract class 'undefined' | ||
var b = new Foo(); // Error because of invalid constructor arguments | ||
~~~~~~~~~ | ||
!!! error TS2346: Supplied parameters do not match any signature of call target. | ||
~~~~~~~~~ | ||
!!! error TS2501: Cannot create an instance of the abstract class 'undefined' | ||
|
||
|
||
// Valid | ||
|
||
var c = new Bar(1); | ||
c.empty(); | ||
|
||
// Calling a static method on a abstract class is valid | ||
Foo.bar(); | ||
|
||
var Copy = Foo; | ||
new Copy(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We want this to be allowed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about abstract class A {
}
import alias = A;
new alias(); I would argue this has to be an error.. else There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if this is the case, the check should not use type.symbol, it should use resolveName at this location, and only be restricted to identifiers and qualified names. this looks like a more correct approach though. i think you can always cast to something that is not abstract to get away with it.. it feels a lot like privates in classes that we preserve on the type. |
||
~~~~~~~~~~ | ||
!!! error TS2346: Supplied parameters do not match any signature of call target. | ||
~~~~~~~~~~ | ||
!!! error TS2501: Cannot create an instance of the abstract class 'undefined' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
//// [abstractClass1.ts] | ||
|
||
abstract class Foo { | ||
constructor(f: any) { } | ||
public static bar(): void { } | ||
|
||
public empty() { } | ||
} | ||
|
||
class Bar extends Foo { | ||
constructor(f: any) { | ||
super(f); | ||
} | ||
} | ||
|
||
var a = new Foo(1); // Error | ||
var b = new Foo(); // Error because of invalid constructor arguments | ||
|
||
|
||
// Valid | ||
|
||
var c = new Bar(1); | ||
c.empty(); | ||
|
||
// Calling a static method on a abstract class is valid | ||
Foo.bar(); | ||
|
||
var Copy = Foo; | ||
new Copy(); | ||
|
||
|
||
//// [abstractClass1.js] | ||
var __extends = this.__extends || function (d, b) { | ||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; | ||
function __() { this.constructor = d; } | ||
__.prototype = b.prototype; | ||
d.prototype = new __(); | ||
}; | ||
var Foo = (function () { | ||
function Foo(f) { | ||
} | ||
Foo.bar = function () { }; | ||
Foo.prototype.empty = function () { }; | ||
return Foo; | ||
})(); | ||
var Bar = (function (_super) { | ||
__extends(Bar, _super); | ||
function Bar(f) { | ||
_super.call(this, f); | ||
} | ||
return Bar; | ||
})(Foo); | ||
var a = new Foo(1); // Error | ||
var b = new Foo(); // Error because of invalid constructor arguments | ||
// Valid | ||
var c = new Bar(1); | ||
c.empty(); | ||
// Calling a static method on a abstract class is valid | ||
Foo.bar(); | ||
var Copy = Foo; | ||
new Copy(); | ||
|
||
|
||
//// [abstractClass1.d.ts] | ||
declare abstract class Foo { | ||
constructor(f: any); | ||
static bar(): void; | ||
empty(): void; | ||
} | ||
declare class Bar extends Foo { | ||
constructor(f: any); | ||
} | ||
declare var a: Foo; | ||
declare var b: any; | ||
declare var c: Bar; | ||
declare var Copy: typeof Foo; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// @declaration: true | ||
|
||
abstract class Foo { | ||
constructor(f: any) { } | ||
public static bar(): void { } | ||
|
||
public empty() { } | ||
} | ||
|
||
class Bar extends Foo { | ||
constructor(f: any) { | ||
super(f); | ||
} | ||
} | ||
|
||
var a = new Foo(1); // Error | ||
var b = new Foo(); // Error because of invalid constructor arguments | ||
|
||
|
||
// Valid | ||
|
||
var c = new Bar(1); | ||
c.empty(); | ||
|
||
// Calling a static method on a abstract class is valid | ||
Foo.bar(); | ||
|
||
var Copy = Foo; | ||
new Copy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not use
null
; useundefined