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);
|
||||
|
||||
Reference in New Issue
Block a user