Skip to content

Commit

Permalink
Plain JS grammar errors (#47067)
Browse files Browse the repository at this point in the history
* Plain JS grammar errors

From the list in
#45349 (comment),
excluding the JSX errors, decorator errors and unresolved #private
error. The latter re-uses "Cannot resolve name X" which naturally shows
up a *lot* in plain JS.

* Add grammarErrorAtPos errors

Also remove checkGrammarArguments; it's blocked entirely by the same
parser error.
  • Loading branch information
sandersn committed Dec 8, 2021
1 parent 0225425 commit a72bf54
Show file tree
Hide file tree
Showing 9 changed files with 2,059 additions and 20 deletions.
19 changes: 2 additions & 17 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31013,7 +31013,7 @@ namespace ts {
* @returns On success, the expression's signature's return type. On failure, anyType.
*/
function checkCallExpression(node: CallExpression | NewExpression, checkMode?: CheckMode): Type {
if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments);
checkGrammarTypeArguments(node, node.typeArguments);

const signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode);
if (signature === resolvingSignature) {
Expand Down Expand Up @@ -31133,7 +31133,7 @@ namespace ts {

function checkImportCallExpression(node: ImportCall): Type {
// Check grammar of dynamic import
if (!checkGrammarArguments(node.arguments)) checkGrammarImportCallExpression(node);
checkGrammarImportCallExpression(node);

if (node.arguments.length === 0) {
return createPromiseReturnType(node, anyType);
Expand Down Expand Up @@ -42917,21 +42917,6 @@ namespace ts {
return false;
}

function checkGrammarForOmittedArgument(args: NodeArray<Expression> | undefined): boolean {
if (args) {
for (const arg of args) {
if (arg.kind === SyntaxKind.OmittedExpression) {
return grammarErrorAtPos(arg, arg.pos, 0, Diagnostics.Argument_expression_expected);
}
}
}
return false;
}

function checkGrammarArguments(args: NodeArray<Expression> | undefined): boolean {
return checkGrammarForOmittedArgument(args);
}

function checkGrammarHeritageClause(node: HeritageClause): boolean {
const types = node.types;
if (checkGrammarForDisallowedTrailingComma(types)) {
Expand Down
67 changes: 66 additions & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ namespace ts {

/** @internal */
export const plainJSErrors: Set<number> = new Set([
// binder errors
Diagnostics.Cannot_redeclare_block_scoped_variable_0.code,
Diagnostics.A_module_cannot_have_multiple_default_exports.code,
Diagnostics.Another_export_default_is_here.code,
Expand All @@ -835,6 +836,69 @@ namespace ts {
Diagnostics.A_label_is_not_allowed_here.code,
Diagnostics.Octal_literals_are_not_allowed_in_strict_mode.code,
Diagnostics.with_statements_are_not_allowed_in_strict_mode.code,
// grammar errors
Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement.code,
Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement.code,
Diagnostics.A_class_member_cannot_have_the_0_keyword.code,
Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name.code,
Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement.code,
Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement.code,
Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement.code,
Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement.code,
Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context.code,
Diagnostics.A_destructuring_declaration_must_have_an_initializer.code,
Diagnostics.A_get_accessor_cannot_have_parameters.code,
Diagnostics.A_rest_element_cannot_contain_a_binding_pattern.code,
Diagnostics.A_rest_element_cannot_have_a_property_name.code,
Diagnostics.A_rest_element_cannot_have_an_initializer.code,
Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern.code,
Diagnostics.A_rest_parameter_cannot_have_an_initializer.code,
Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list.code,
Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma.code,
Diagnostics.A_set_accessor_cannot_have_rest_parameter.code,
Diagnostics.A_set_accessor_must_have_exactly_one_parameter.code,
Diagnostics.An_object_member_cannot_be_declared_optional.code,
Diagnostics.Argument_of_dynamic_import_cannot_be_spread_element.code,
Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable.code,
Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause.code,
Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator.code,
Diagnostics.Classes_may_not_have_a_field_named_constructor.code,
Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern.code,
Diagnostics.Duplicate_label_0.code,
Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments.code,
Diagnostics.For_await_loops_cannot_be_used_inside_a_class_static_block.code,
Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression.code,
Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name.code,
Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array.code,
Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names.code,
Diagnostics.Jump_target_cannot_cross_function_boundary.code,
Diagnostics.Line_terminator_not_permitted_before_arrow.code,
Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement.code,
Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement.code,
Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies.code,
Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression.code,
Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_identifier.code,
Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain.code,
Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async.code,
Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer.code,
Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer.code,
Diagnostics.Trailing_comma_not_allowed.code,
Diagnostics.Variable_declaration_list_cannot_be_empty.code,
Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses.code,
Diagnostics._0_expected.code,
Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2.code,
Diagnostics._0_list_cannot_be_empty.code,
Diagnostics._0_modifier_already_seen.code,
Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration.code,
Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element.code,
Diagnostics._0_modifier_cannot_appear_on_a_parameter.code,
Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind.code,
Diagnostics._0_modifier_cannot_be_used_here.code,
Diagnostics._0_modifier_must_precede_1_modifier.code,
Diagnostics.const_declarations_can_only_be_declared_inside_a_block.code,
Diagnostics.const_declarations_must_be_initialized.code,
Diagnostics.let_declarations_can_only_be_declared_inside_a_block.code,
Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations.code,
]);

/**
Expand Down Expand Up @@ -2036,9 +2100,10 @@ namespace ts {
const includeBindAndCheckDiagnostics = !isTsNoCheck && (sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX
|| sourceFile.scriptKind === ScriptKind.External || isPlainJs || isCheckJs || sourceFile.scriptKind === ScriptKind.Deferred);
let bindDiagnostics: readonly Diagnostic[] = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray;
const checkDiagnostics = includeBindAndCheckDiagnostics && !isPlainJs ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray;
let checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray;
if (isPlainJs) {
bindDiagnostics = filter(bindDiagnostics, d => plainJSErrors.has(d.code));
checkDiagnostics = filter(checkDiagnostics, d => plainJSErrors.has(d.code));
}
// skip ts-expect-error errors in plain JS files, and skip JSDoc errors except in checked JS
return getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics && !isPlainJs, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined);
Expand Down
5 changes: 4 additions & 1 deletion tests/baselines/reference/plainJSBinderErrors.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ tests/cases/conformance/salsa/plainJSBinderErrors.js(22,15): error TS1210: Code
tests/cases/conformance/salsa/plainJSBinderErrors.js(23,15): error TS1210: Code contained in a class is evaluated in JavaScript's strict mode which does not allow this use of 'arguments'. For more information, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode.
tests/cases/conformance/salsa/plainJSBinderErrors.js(27,9): error TS1101: 'with' statements are not allowed in strict mode.
tests/cases/conformance/salsa/plainJSBinderErrors.js(33,13): error TS1344: 'A label is not allowed here.
tests/cases/conformance/salsa/plainJSBinderErrors.js(34,13): error TS1107: Jump target cannot cross function boundary.
tests/cases/conformance/salsa/plainJSBinderErrors.js(39,7): error TS1215: Invalid use of 'eval'. Modules are automatically in strict mode.
tests/cases/conformance/salsa/plainJSBinderErrors.js(40,7): error TS1215: Invalid use of 'arguments'. Modules are automatically in strict mode.


==== tests/cases/conformance/salsa/plainJSBinderErrors.js (16 errors) ====
==== tests/cases/conformance/salsa/plainJSBinderErrors.js (17 errors) ====
export default 12
~~~~~~~~~~~~~~~~~
!!! error TS2528: A module cannot have multiple default exports.
Expand Down Expand Up @@ -81,6 +82,8 @@ tests/cases/conformance/salsa/plainJSBinderErrors.js(40,7): error TS1215: Invali
~~~~~
!!! error TS1344: 'A label is not allowed here.
break label
~~~~~~~~~~~
!!! error TS1107: Jump target cannot cross function boundary.
}
return x
}
Expand Down

0 comments on commit a72bf54

Please sign in to comment.