mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Parse quoted constructors as constructors, not methods (#31949)
* Parse quoted constructors as constructors, not methods * Update baselines * Fix disambiguation between quoted constructor and property named constructor * Clean up parsing a bit * Support escapes in constructor name * Update baselines
This commit is contained in:
@@ -33017,9 +33017,6 @@ namespace ts {
|
||||
return grammarErrorAtPos(node, node.end - 1, ";".length, Diagnostics._0_expected, "{");
|
||||
}
|
||||
}
|
||||
else if (isClassLike(node.parent) && isStringLiteral(node.name) && node.name.text === "constructor" && (!compilerOptions.target || compilerOptions.target < ScriptTarget.ES5)) {
|
||||
return grammarErrorOnNode(node.name, Diagnostics.Quoted_constructors_have_previously_been_interpreted_as_methods_which_is_incorrect_In_TypeScript_3_6_they_will_be_correctly_parsed_as_constructors_In_the_meantime_consider_using_constructor_to_write_a_constructor_or_constructor_to_write_a_method);
|
||||
}
|
||||
if (checkGrammarForGenerator(node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5113,10 +5113,6 @@
|
||||
"category": "Error",
|
||||
"code": 18004
|
||||
},
|
||||
"Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '[\"constructor\"]()' to write a method.": {
|
||||
"category": "Error",
|
||||
"code": 18005
|
||||
},
|
||||
"Classes may not have a field named 'constructor'.": {
|
||||
"category": "Error",
|
||||
"code": 18006
|
||||
|
||||
+26
-8
@@ -5656,12 +5656,27 @@ namespace ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseConstructorDeclaration(node: ConstructorDeclaration): ConstructorDeclaration {
|
||||
node.kind = SyntaxKind.Constructor;
|
||||
parseExpected(SyntaxKind.ConstructorKeyword);
|
||||
fillSignature(SyntaxKind.ColonToken, SignatureFlags.None, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected);
|
||||
return finishNode(node);
|
||||
function parseConstructorName() {
|
||||
if (token() === SyntaxKind.ConstructorKeyword) {
|
||||
return parseExpected(SyntaxKind.ConstructorKeyword);
|
||||
}
|
||||
if (token() === SyntaxKind.StringLiteral && lookAhead(nextToken) === SyntaxKind.OpenParenToken) {
|
||||
return tryParse(() => {
|
||||
const literalNode = parseLiteralNode();
|
||||
return literalNode.text === "constructor" ? literalNode : undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function tryParseConstructorDeclaration(node: ConstructorDeclaration): ConstructorDeclaration | undefined {
|
||||
return tryParse(() => {
|
||||
if (parseConstructorName()) {
|
||||
node.kind = SyntaxKind.Constructor;
|
||||
fillSignature(SyntaxKind.ColonToken, SignatureFlags.None, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected);
|
||||
return finishNode(node);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function parseMethodDeclaration(node: MethodDeclaration, asteriskToken: AsteriskToken, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
|
||||
@@ -5867,8 +5882,11 @@ namespace ts {
|
||||
return parseAccessorDeclaration(<AccessorDeclaration>node, SyntaxKind.SetAccessor);
|
||||
}
|
||||
|
||||
if (token() === SyntaxKind.ConstructorKeyword) {
|
||||
return parseConstructorDeclaration(<ConstructorDeclaration>node);
|
||||
if (token() === SyntaxKind.ConstructorKeyword || token() === SyntaxKind.StringLiteral) {
|
||||
const constructorDeclaration = tryParseConstructorDeclaration(<ConstructorDeclaration>node);
|
||||
if (constructorDeclaration) {
|
||||
return constructorDeclaration;
|
||||
}
|
||||
}
|
||||
|
||||
if (isIndexSignature()) {
|
||||
|
||||
@@ -3150,6 +3150,23 @@ namespace ts {
|
||||
return s.replace(escapedCharsRegExp, getReplacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip off existed single quotes or double quotes from a given string
|
||||
*
|
||||
* @return non-quoted string
|
||||
*/
|
||||
export function stripQuotes(name: string) {
|
||||
const length = name.length;
|
||||
if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && startsWithQuote(name)) {
|
||||
return name.substring(1, length - 1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
export function startsWithQuote(name: string): boolean {
|
||||
return isSingleOrDoubleQuote(name.charCodeAt(0));
|
||||
}
|
||||
|
||||
function getReplacement(c: string, offset: number, input: string) {
|
||||
if (c.charCodeAt(0) === CharacterCodes.nullCharacter) {
|
||||
const lookAhead = input.charCodeAt(offset + c.length);
|
||||
|
||||
@@ -1636,23 +1636,6 @@ namespace ts {
|
||||
return !!location.parent && isImportOrExportSpecifier(location.parent) && location.parent.propertyName === location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip off existed single quotes or double quotes from a given string
|
||||
*
|
||||
* @return non-quoted string
|
||||
*/
|
||||
export function stripQuotes(name: string) {
|
||||
const length = name.length;
|
||||
if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && startsWithQuote(name)) {
|
||||
return name.substring(1, length - 1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
export function startsWithQuote(name: string): boolean {
|
||||
return isSingleOrDoubleQuote(name.charCodeAt(0));
|
||||
}
|
||||
|
||||
export function scriptKindIs(fileName: string, host: LanguageServiceHost, ...scriptKinds: ScriptKind[]): boolean {
|
||||
const scriptKind = getScriptKind(fileName, host);
|
||||
return some(scriptKinds, k => k === scriptKind);
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts(2,5): error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
|
||||
tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts(6,5): error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
|
||||
tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts(14,5): error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
|
||||
|
||||
|
||||
==== tests/cases/conformance/classes/constructorDeclarations/quotedConstructors.ts (3 errors) ====
|
||||
class C {
|
||||
"constructor"() {} // Error in 3.5
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
|
||||
}
|
||||
|
||||
class D {
|
||||
'constructor'() {} // Error in 3.5
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
|
||||
}
|
||||
|
||||
class E {
|
||||
['constructor']() {}
|
||||
}
|
||||
|
||||
new class {
|
||||
"constructor"() {} // Error in 3.5
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS18005: Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '["constructor"]()' to write a method.
|
||||
};
|
||||
|
||||
var o = { "constructor"() {} };
|
||||
|
||||
@@ -1,46 +1,68 @@
|
||||
//// [quotedConstructors.ts]
|
||||
class C {
|
||||
"constructor"() {} // Error in 3.5
|
||||
"constructor"() {
|
||||
console.log(this);
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
'constructor'() {} // Error in 3.5
|
||||
'constructor'() {
|
||||
console.log(this);
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
['constructor']() {}
|
||||
['constructor']() {
|
||||
console.log(this);
|
||||
}
|
||||
}
|
||||
|
||||
new class {
|
||||
"constructor"() {} // Error in 3.5
|
||||
"constructor"() {
|
||||
console.log(this);
|
||||
}
|
||||
};
|
||||
|
||||
var o = { "constructor"() {} };
|
||||
|
||||
class F {
|
||||
"\x63onstructor"() {
|
||||
console.log(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [quotedConstructors.js]
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
console.log(this);
|
||||
}
|
||||
C.prototype["constructor"] = function () { }; // Error in 3.5
|
||||
return C;
|
||||
}());
|
||||
var D = /** @class */ (function () {
|
||||
function D() {
|
||||
console.log(this);
|
||||
}
|
||||
D.prototype['constructor'] = function () { }; // Error in 3.5
|
||||
return D;
|
||||
}());
|
||||
var E = /** @class */ (function () {
|
||||
function E() {
|
||||
}
|
||||
E.prototype['constructor'] = function () { };
|
||||
E.prototype['constructor'] = function () {
|
||||
console.log(this);
|
||||
};
|
||||
return E;
|
||||
}());
|
||||
new /** @class */ (function () {
|
||||
function class_1() {
|
||||
console.log(this);
|
||||
}
|
||||
class_1.prototype["constructor"] = function () { }; // Error in 3.5
|
||||
return class_1;
|
||||
}());
|
||||
var o = { "constructor": function () { } };
|
||||
var F = /** @class */ (function () {
|
||||
function F() {
|
||||
console.log(this);
|
||||
}
|
||||
return F;
|
||||
}());
|
||||
|
||||
@@ -2,32 +2,65 @@
|
||||
class C {
|
||||
>C : Symbol(C, Decl(quotedConstructors.ts, 0, 0))
|
||||
|
||||
"constructor"() {} // Error in 3.5
|
||||
>"constructor" : Symbol(C["constructor"], Decl(quotedConstructors.ts, 0, 9))
|
||||
"constructor"() {
|
||||
console.log(this);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>this : Symbol(C, Decl(quotedConstructors.ts, 0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
>D : Symbol(D, Decl(quotedConstructors.ts, 2, 1))
|
||||
>D : Symbol(D, Decl(quotedConstructors.ts, 4, 1))
|
||||
|
||||
'constructor'() {} // Error in 3.5
|
||||
>'constructor' : Symbol(D['constructor'], Decl(quotedConstructors.ts, 4, 9))
|
||||
'constructor'() {
|
||||
console.log(this);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>this : Symbol(D, Decl(quotedConstructors.ts, 4, 1))
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
>E : Symbol(E, Decl(quotedConstructors.ts, 6, 1))
|
||||
>E : Symbol(E, Decl(quotedConstructors.ts, 10, 1))
|
||||
|
||||
['constructor']() {}
|
||||
>['constructor'] : Symbol(E['constructor'], Decl(quotedConstructors.ts, 8, 9))
|
||||
>'constructor' : Symbol(E['constructor'], Decl(quotedConstructors.ts, 8, 9))
|
||||
['constructor']() {
|
||||
>['constructor'] : Symbol(E['constructor'], Decl(quotedConstructors.ts, 12, 9))
|
||||
>'constructor' : Symbol(E['constructor'], Decl(quotedConstructors.ts, 12, 9))
|
||||
|
||||
console.log(this);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>this : Symbol(E, Decl(quotedConstructors.ts, 10, 1))
|
||||
}
|
||||
}
|
||||
|
||||
new class {
|
||||
"constructor"() {} // Error in 3.5
|
||||
>"constructor" : Symbol((Anonymous class)["constructor"], Decl(quotedConstructors.ts, 12, 11))
|
||||
|
||||
"constructor"() {
|
||||
console.log(this);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>this : Symbol((Anonymous class), Decl(quotedConstructors.ts, 18, 3))
|
||||
}
|
||||
};
|
||||
|
||||
var o = { "constructor"() {} };
|
||||
>o : Symbol(o, Decl(quotedConstructors.ts, 16, 3))
|
||||
>"constructor" : Symbol("constructor", Decl(quotedConstructors.ts, 16, 9))
|
||||
>o : Symbol(o, Decl(quotedConstructors.ts, 24, 3))
|
||||
>"constructor" : Symbol("constructor", Decl(quotedConstructors.ts, 24, 9))
|
||||
|
||||
class F {
|
||||
>F : Symbol(F, Decl(quotedConstructors.ts, 24, 31))
|
||||
|
||||
"\x63onstructor"() {
|
||||
console.log(this);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>this : Symbol(F, Decl(quotedConstructors.ts, 24, 31))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,32 +2,57 @@
|
||||
class C {
|
||||
>C : C
|
||||
|
||||
"constructor"() {} // Error in 3.5
|
||||
>"constructor" : () => void
|
||||
"constructor"() {
|
||||
console.log(this);
|
||||
>console.log(this) : void
|
||||
>console.log : (message?: any, ...optionalParams: any[]) => void
|
||||
>console : Console
|
||||
>log : (message?: any, ...optionalParams: any[]) => void
|
||||
>this : this
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
>D : D
|
||||
|
||||
'constructor'() {} // Error in 3.5
|
||||
>'constructor' : () => void
|
||||
'constructor'() {
|
||||
console.log(this);
|
||||
>console.log(this) : void
|
||||
>console.log : (message?: any, ...optionalParams: any[]) => void
|
||||
>console : Console
|
||||
>log : (message?: any, ...optionalParams: any[]) => void
|
||||
>this : this
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
>E : E
|
||||
|
||||
['constructor']() {}
|
||||
['constructor']() {
|
||||
>['constructor'] : () => void
|
||||
>'constructor' : "constructor"
|
||||
|
||||
console.log(this);
|
||||
>console.log(this) : void
|
||||
>console.log : (message?: any, ...optionalParams: any[]) => void
|
||||
>console : Console
|
||||
>log : (message?: any, ...optionalParams: any[]) => void
|
||||
>this : this
|
||||
}
|
||||
}
|
||||
|
||||
new class {
|
||||
>new class { "constructor"() {} // Error in 3.5} : (Anonymous class)
|
||||
>class { "constructor"() {} // Error in 3.5} : typeof (Anonymous class)
|
||||
|
||||
"constructor"() {} // Error in 3.5
|
||||
>"constructor" : () => void
|
||||
>new class { "constructor"() { console.log(this); }} : (Anonymous class)
|
||||
>class { "constructor"() { console.log(this); }} : typeof (Anonymous class)
|
||||
|
||||
"constructor"() {
|
||||
console.log(this);
|
||||
>console.log(this) : void
|
||||
>console.log : (message?: any, ...optionalParams: any[]) => void
|
||||
>console : Console
|
||||
>log : (message?: any, ...optionalParams: any[]) => void
|
||||
>this : this
|
||||
}
|
||||
};
|
||||
|
||||
var o = { "constructor"() {} };
|
||||
@@ -35,3 +60,16 @@ var o = { "constructor"() {} };
|
||||
>{ "constructor"() {} } : { "constructor"(): void; }
|
||||
>"constructor" : () => void
|
||||
|
||||
class F {
|
||||
>F : F
|
||||
|
||||
"\x63onstructor"() {
|
||||
console.log(this);
|
||||
>console.log(this) : void
|
||||
>console.log : (message?: any, ...optionalParams: any[]) => void
|
||||
>console : Console
|
||||
>log : (message?: any, ...optionalParams: any[]) => void
|
||||
>this : this
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
class C {
|
||||
"constructor"() {} // Error in 3.5
|
||||
"constructor"() {
|
||||
console.log(this);
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
'constructor'() {} // Error in 3.5
|
||||
'constructor'() {
|
||||
console.log(this);
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
['constructor']() {}
|
||||
['constructor']() {
|
||||
console.log(this);
|
||||
}
|
||||
}
|
||||
|
||||
new class {
|
||||
"constructor"() {} // Error in 3.5
|
||||
"constructor"() {
|
||||
console.log(this);
|
||||
}
|
||||
};
|
||||
|
||||
var o = { "constructor"() {} };
|
||||
|
||||
class F {
|
||||
"\x63onstructor"() {
|
||||
console.log(this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user