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:
Andrew Branch
2019-07-12 14:01:57 -07:00
committed by GitHub
parent 37f2e5972f
commit 4f3412153a
10 changed files with 186 additions and 98 deletions
-3
View File
@@ -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;
}
-4
View File
@@ -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
View File
@@ -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()) {
+17
View File
@@ -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);
-17
View File
@@ -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);