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

Disallow line terminator after arrow function parameters, before => #2283

Merged
merged 10 commits into from Mar 16, 2015
31 changes: 22 additions & 9 deletions src/compiler/checker.ts
Expand Up @@ -448,7 +448,7 @@ module ts {
let declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) ? d : undefined);

Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");

// first check if usage is lexically located after the declaration
let isUsedBeforeDeclaration = !isDefinedBefore(declaration, errorLocation);
if (!isUsedBeforeDeclaration) {
Expand All @@ -465,7 +465,7 @@ module ts {

if (variableDeclaration.parent.parent.kind === SyntaxKind.VariableStatement ||
variableDeclaration.parent.parent.kind === SyntaxKind.ForStatement) {
// variable statement/for statement case,
// variable statement/for statement case,
// use site should not be inside variable declaration (initializer of declaration or binding element)
isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, variableDeclaration, container);
}
Expand Down Expand Up @@ -4412,7 +4412,7 @@ module ts {
}

/**
* Check if a Type was written as a tuple type literal.
* Check if a Type was written as a tuple type literal.
* Prefer using isTupleLikeType() unless the use of `elementTypes` is required.
*/
function isTupleType(type: Type) : boolean {
Expand Down Expand Up @@ -9080,7 +9080,7 @@ module ts {
*/
function checkElementTypeOfArrayOrString(arrayOrStringType: Type, expressionForError: Expression): Type {
Debug.assert(languageVersion < ScriptTarget.ES6);

// After we remove all types that are StringLike, we will know if there was a string constituent
// based on whether the remaining type is the same as the initial type.
let arrayType = removeTypesFromUnionType(arrayOrStringType, TypeFlags.StringLike, /*isTypeOfKind*/ true, /*allowEmptyUnionResult*/ true);
Expand Down Expand Up @@ -11324,16 +11324,15 @@ module ts {
}
}

function checkGrammarTypeParameterList(node: FunctionLikeDeclaration, typeParameters: NodeArray<TypeParameterDeclaration>): boolean {
function checkGrammarTypeParameterList(node: FunctionLikeDeclaration, typeParameters: NodeArray<TypeParameterDeclaration>, file: SourceFile): boolean {
if (checkGrammarForDisallowedTrailingComma(typeParameters)) {
return true;
}

if (typeParameters && typeParameters.length === 0) {
let start = typeParameters.pos - "<".length;
let sourceFile = getSourceFileOfNode(node);
let end = skipTrivia(sourceFile.text, typeParameters.end) + ">".length;
return grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.Type_parameter_list_cannot_be_empty);
let end = skipTrivia(file.text, typeParameters.end) + ">".length;
return grammarErrorAtPos(file, start, end - start, Diagnostics.Type_parameter_list_cannot_be_empty);
}
}

Expand Down Expand Up @@ -11377,7 +11376,21 @@ module ts {

function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
// Prevent cascading error by short-circuit
return checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters) || checkGrammarParameterList(node.parameters);
let file = getSourceFileOfNode(node);
return checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters, file) ||
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
}

function checkGrammarArrowFunction(node: FunctionLikeDeclaration, file: SourceFile): boolean {
if (node.kind === SyntaxKind.ArrowFunction) {
let arrowFunction = <ArrowFunction>node;
let startLine = getLineAndCharacterOfPosition(file, arrowFunction.equalsGreaterThanToken.pos).line;
let endLine = getLineAndCharacterOfPosition(file, arrowFunction.equalsGreaterThanToken.end).line;
if (startLine !== endLine) {
return grammarErrorOnNode(arrowFunction.equalsGreaterThanToken, Diagnostics.Line_terminator_not_permitted_before_arrow);
}
}
return false;
}

function checkGrammarIndexSignatureParameters(node: SignatureDeclaration): boolean {
Expand Down
1 change: 1 addition & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Expand Up @@ -157,6 +157,7 @@ module ts {
Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." },
Unterminated_Unicode_escape_sequence: { code: 1199, category: DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." },
Line_terminator_not_permitted_before_arrow: { code: 1200, category: DiagnosticCategory.Error, key: "Line terminator not permitted before arrow." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Expand Up @@ -619,6 +619,10 @@
"category": "Error",
"code": 1199
},
"Line terminator not permitted before arrow.": {
"category": "Error",
"code": 1200
},
"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2300
Expand Down