feat(semantic): check for illegal symbol modifiers (#3838)

This commit is contained in:
Don Isaac 2024-06-23 00:36:09 -04:00 committed by GitHub
parent a6487482bc
commit d5f6aeb1ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 717 additions and 55 deletions

View file

@ -1339,7 +1339,16 @@ impl<'a> Modifiers<'a> {
.map_or(false, |modifiers| modifiers.iter().any(|modifier| modifier.kind == target))
}
pub fn find<F>(&self, f: F) -> Option<&Modifier>
pub fn iter(&self) -> impl Iterator<Item = &Modifier> + '_ {
self.0.as_ref().into_iter().flat_map(|modifiers| modifiers.iter())
}
/// Find a modifier by kind
pub fn find(&self, kind: ModifierKind) -> Option<&Modifier> {
self.find_where(|modifier| modifier.kind == kind)
}
pub fn find_where<F>(&self, f: F) -> Option<&Modifier>
where
F: Fn(&Modifier) -> bool,
{

View file

@ -41,8 +41,9 @@ declare_oxc_lint!(
impl Rule for NoConstEnum {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::TSEnumDeclaration(enum_decl) = node.kind() {
let Some(const_enum) =
enum_decl.modifiers.find(|modifier| matches!(modifier.kind, ModifierKind::Const))
let Some(const_enum) = enum_decl
.modifiers
.find_where(|modifier| matches!(modifier.kind, ModifierKind::Const))
else {
return;
};

View file

@ -34,6 +34,7 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
AstKind::RegExpLiteral(lit) => js::check_regexp_literal(lit, ctx),
AstKind::Directive(dir) => js::check_directive(dir, ctx),
AstKind::Function(func) => ts::check_function(func, node, ctx),
AstKind::ModuleDeclaration(decl) => {
js::check_module_declaration(decl, node, ctx);
}
@ -68,8 +69,10 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
js::check_function_declaration(alternate, true, ctx);
}
}
AstKind::Class(class) => js::check_class(class, node, ctx),
AstKind::Class(class) => {
js::check_class(class, node, ctx);
ts::check_class(class, node, ctx);
}
AstKind::MethodDefinition(method) => js::check_method_definition(method, ctx),
AstKind::ObjectProperty(prop) => js::check_object_property(prop, ctx),
AstKind::Super(sup) => js::check_super(sup, node, ctx),
@ -91,13 +94,20 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
AstKind::ObjectExpression(expr) => js::check_object_expression(expr, ctx),
AstKind::UnaryExpression(expr) => js::check_unary_expression(expr, node, ctx),
AstKind::YieldExpression(expr) => js::check_yield_expression(expr, node, ctx),
AstKind::VariableDeclaration(decl) => ts::check_variable_declaration(decl, node, ctx),
AstKind::VariableDeclarator(decl) => ts::check_variable_declarator(decl, ctx),
AstKind::SimpleAssignmentTarget(target) => ts::check_simple_assignment_target(target, ctx),
AstKind::TSTypeParameterDeclaration(declaration) => {
ts::check_ts_type_parameter_declaration(declaration, ctx);
}
AstKind::TSModuleDeclaration(decl) => ts::check_ts_module_declaration(decl, ctx),
AstKind::TSEnumDeclaration(decl) => ts::check_ts_enum_declaration(decl, ctx),
AstKind::TSModuleDeclaration(decl) => ts::check_ts_module_declaration(decl, node, ctx),
AstKind::TSEnumDeclaration(decl) => ts::check_ts_enum_declaration(decl, node, ctx),
AstKind::TSTypeAliasDeclaration(decl) => {
ts::check_ts_type_alias_declaration(decl, node, ctx);
}
AstKind::TSInterfaceDeclaration(decl) => {
ts::check_ts_interface_declaration(decl, node, ctx);
}
_ => {}
}
}

View file

@ -3,9 +3,10 @@ use oxc_ast::syntax_directed_operations::BoundNames;
use oxc_ast::{ast::*, AstKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{Atom, GetSpan, Span};
use oxc_syntax::scope::ScopeFlags;
use rustc_hash::FxHashMap;
use crate::{builder::SemanticBuilder, diagnostics::redeclaration};
use crate::{builder::SemanticBuilder, diagnostics::redeclaration, AstNode};
fn empty_type_parameter_list(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Type parameter list cannot be empty.").with_labels([span0.into()])
@ -23,7 +24,6 @@ pub fn check_ts_type_parameter_declaration(
fn unexpected_optional(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Unexpected `?` operator").with_labels([span0.into()])
}
#[allow(clippy::cast_possible_truncation)]
pub fn check_variable_declarator(decl: &VariableDeclarator, ctx: &SemanticBuilder<'_>) {
if decl.id.optional {
@ -114,6 +114,94 @@ pub fn check_array_pattern<'a>(pattern: &ArrayPattern<'a>, ctx: &SemanticBuilder
}
}
/// ts(1184)
fn modifiers_cannot_be_used_here(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Modifiers cannot be used here.").with_labels([span.into()])
}
/// ts(1024)
fn readonly_only_on_index_signature_or_property_decl(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"'readonly' modifier can only appear on a property declaration or index signature.",
)
.with_labels([span.into()])
}
/// ts(1042)
fn async_cannot_be_used_here(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("'async' modifier cannot be used here.").with_labels([span.into()])
}
/// Returns `true` if the scope described by `scope_flags` supports export
/// declarations or specifiers.
pub const fn scope_can_export(scope_flags: ScopeFlags) -> bool {
const CAN_EXPORT: ScopeFlags = ScopeFlags::Top.union(ScopeFlags::TsModuleBlock);
scope_flags.contains(CAN_EXPORT)
}
fn check_declaration_modifiers<'a>(
modifiers: &Modifiers<'a>,
decl_node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
let scope_flags = ctx.scope.get_flags(decl_node.scope_id());
let kind = decl_node.kind();
let is_class = matches!(kind, AstKind::Class(_));
let is_function = matches!(kind, AstKind::Function(_));
for modifier in modifiers.iter() {
match modifier.kind {
ModifierKind::Public
| ModifierKind::Private
| ModifierKind::Protected
| ModifierKind::Static
| ModifierKind::Override => {
ctx.error(modifiers_cannot_be_used_here(modifier.span));
}
ModifierKind::Abstract if !is_class => {
ctx.error(modifiers_cannot_be_used_here(modifier.span));
}
ModifierKind::Async if !is_function => {
ctx.error(async_cannot_be_used_here(modifier.span));
}
ModifierKind::Readonly => {
ctx.error(readonly_only_on_index_signature_or_property_decl(modifier.span));
}
ModifierKind::Export if !scope_can_export(scope_flags) => {
ctx.error(modifiers_cannot_be_used_here(modifier.span));
}
_ => {}
}
}
}
pub fn check_variable_declaration<'a>(
decl: &VariableDeclaration<'a>,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
check_declaration_modifiers(&decl.modifiers, node, ctx);
}
pub fn check_function<'a>(function: &Function<'a>, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
check_declaration_modifiers(&function.modifiers, node, ctx);
}
pub fn check_class<'a>(class: &Class<'a>, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
check_declaration_modifiers(&class.modifiers, node, ctx);
}
pub fn check_ts_type_alias_declaration<'a>(
decl: &TSTypeAliasDeclaration<'a>,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
check_declaration_modifiers(&decl.modifiers, node, ctx);
}
pub fn check_ts_interface_declaration<'a>(
decl: &TSInterfaceDeclaration<'a>,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
check_declaration_modifiers(&decl.modifiers, node, ctx);
}
fn not_allowed_namespace_declaration(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"A namespace declaration is only allowed at the top level of a namespace or module.",
@ -121,7 +209,12 @@ fn not_allowed_namespace_declaration(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
pub fn check_ts_module_declaration<'a>(decl: &TSModuleDeclaration<'a>, ctx: &SemanticBuilder<'a>) {
pub fn check_ts_module_declaration<'a>(
decl: &TSModuleDeclaration<'a>,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
check_declaration_modifiers(&decl.modifiers, node, ctx);
// skip current node
for node in ctx.nodes.iter_parents(ctx.current_node_id).skip(1) {
match node.kind() {
@ -144,8 +237,13 @@ fn enum_member_must_have_initializer(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Enum member must have initializer.").with_labels([span0.into()])
}
pub fn check_ts_enum_declaration(decl: &TSEnumDeclaration<'_>, ctx: &SemanticBuilder<'_>) {
pub fn check_ts_enum_declaration<'a>(
decl: &TSEnumDeclaration<'a>,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
let mut need_initializer = false;
check_declaration_modifiers(&decl.modifiers, node, ctx);
decl.members.iter().for_each(|member| {
#[allow(clippy::unnested_or_patterns)]

View file

@ -1,4 +1,4 @@
use oxc_semantic::SymbolFlags;
use oxc_semantic::{SemanticBuilderReturn, SymbolFlags};
use crate::util::SemanticTester;
@ -46,6 +46,23 @@ fn test_exported_named_function() {
.has_some_symbol("T")
.is_not_exported()
.test();
SemanticTester::tsx(
"
import React from 'react';
export const Counter: React.FC<{ count: number }> = ({ count }) => (
<div>{count}</div>
)
",
)
.has_some_symbol("Counter")
.is_exported()
.contains_flags(
SymbolFlags::ConstVariable
.union(SymbolFlags::BlockScopedVariable)
.union(SymbolFlags::Export),
)
.test();
}
#[test]
@ -149,3 +166,39 @@ fn test_exported_interface() {
test.has_some_symbol("a").is_not_exported().test();
test.has_some_symbol("T").is_not_exported().test();
}
#[test]
fn test_exports_in_namespace() {
let test = SemanticTester::ts(
"
export const x = 1;
namespace N {
function foo() {
return 1
}
export function bar() {
return foo();
}
export const x = 2
}
",
);
test.has_some_symbol("bar").is_exported().test();
let semantic = test.build();
assert!(!semantic.module_record().exported_bindings.contains_key("bar"));
}
#[test]
fn test_export_in_invalid_scope() {
let test = SemanticTester::js(
"
function foo() {
export const x = 1;
}",
)
.expect_errors(true);
test.has_some_symbol("x").contains_flags(SymbolFlags::Export).test();
let SemanticBuilderReturn { semantic, errors } = test.build_with_errors();
assert!(!errors.is_empty(), "expected an export within a function to produce a check error, but no errors were produced");
assert!(semantic.module_record().exported_bindings.is_empty());
}

View file

@ -114,3 +114,20 @@ fn test_export_flag() {
tester.has_root_symbol("b").contains_flags(SymbolFlags::Export).test();
tester.has_root_symbol("c").contains_flags(SymbolFlags::Export).test();
}
#[test]
fn test_invalid_modifiers() {
const PARAM_PROPERTY: &str =
"A parameter property is only allowed in a constructor implementation.";
const ILLEGAL_MODIFIER: &str = "Modifiers cannot be used here.";
const READONLY: &str =
"'readonly' modifier can only appear on a property declaration or index signature.";
SemanticTester::ts("function foo(public x: number) { }").has_error(PARAM_PROPERTY);
// SemanticTester::ts("function foo() { export const x = 1; }").has_error(illegal_modifier);
SemanticTester::ts("function foo() { public const x = 1; }").has_error(ILLEGAL_MODIFIER);
SemanticTester::ts("function foo() { private const x = 1; }").has_error(ILLEGAL_MODIFIER);
SemanticTester::ts("function foo() { protected const x = 1; }").has_error(ILLEGAL_MODIFIER);
SemanticTester::ts("function foo() { abstract const x = 1; }").has_error(ILLEGAL_MODIFIER);
SemanticTester::ts("function foo() { readonly const x = 1; }").has_error(READONLY);
}

View file

@ -9,7 +9,7 @@ use itertools::Itertools;
use oxc_allocator::Allocator;
use oxc_cfg::DisplayDot;
use oxc_diagnostics::{Error, NamedSource, OxcDiagnostic};
use oxc_semantic::{dot::DebugDot, Semantic, SemanticBuilder};
use oxc_semantic::{dot::DebugDot, Semantic, SemanticBuilder, SemanticBuilderReturn};
use oxc_span::SourceType;
pub use symbol_tester::SymbolTester;
@ -18,6 +18,10 @@ pub struct SemanticTester<'a> {
source_type: SourceType,
source_text: &'a str,
cfg: bool,
/// Expect semantic analysis to produce errors.
///
/// Default is `false`.
expect_errors: bool,
}
impl<'a> SemanticTester<'a> {
@ -28,6 +32,13 @@ impl<'a> SemanticTester<'a> {
Self::new(source_text, SourceType::default().with_module(true).with_typescript(true))
}
/// Create a new tester for a TypeScript test case with JSX.
///
/// Use [`SemanticTester::ts`] for TypeScript test cases without JSX.
pub fn tsx(source_text: &'static str) -> Self {
Self::ts(source_text).with_jsx(true)
}
/// Create a new tester for a JavaScript test case.
///
/// Use [`SemanticTester::ts`] for TypeScript test cases.
@ -36,7 +47,13 @@ impl<'a> SemanticTester<'a> {
}
pub fn new(source_text: &'a str, source_type: SourceType) -> Self {
Self { allocator: Allocator::default(), source_type, source_text, cfg: false }
Self {
allocator: Allocator::default(),
source_type,
source_text,
cfg: false,
expect_errors: false,
}
}
/// Set the [`SourceType`] to TypeScript (or JavaScript, using `false`)
@ -64,11 +81,55 @@ impl<'a> SemanticTester<'a> {
self.cfg = yes;
self
}
/// The program being tested is expected to produce errors during semantic analysis.
///
/// By default, programs are expected to be error-free.
///
/// # Example
/// ```
/// use crate::util::{SemanticTester as T};
///
/// // Default behavior. You could omit `expect_errors(false)` here
/// T::js("function foo(a, a) { }").expect_errors(false).has_root_symbol("foo").test()
/// // Not allowed in TS
/// T::ts("function foo(a, a) { }").expect_errors(true).has_root_symbol("foo").test()
/// ```
#[must_use]
pub fn expect_errors(mut self, yes: bool) -> Self {
self.expect_errors = yes;
self
}
/// Parse the source text and produce a new [`Semantic`]
/// Parse the source text and produce a new [`Semantic`].
///
/// Normally this will panic if semantic analysis produces any errors. Use
/// # Panics
/// - if parsing fails
/// - if semantic analysis does/does not produce errors as expected
#[allow(unstable_name_collisions)]
pub fn build(&self) -> Semantic<'_> {
let semantic_ret = self.build_with_errors();
match (self.expect_errors, semantic_ret.errors.is_empty()) {
(true, true) => panic!("Expected errors, but none were produced"),
(false, false) => panic!(
"Semantic analysis failed:\n\n{}",
semantic_ret
.errors
.iter()
.map(ToString::to_string)
.intersperse("\n\n".to_owned())
.collect::<String>()
),
_ => semantic_ret.semantic,
}
}
/// Parse the source text into a new [`Semantic`], but preserves any errors that occur during
/// semantic analysis
/// # Panics
///
#[allow(unstable_name_collisions)]
pub fn build_with_errors(&self) -> SemanticBuilderReturn<'_> {
let parse =
oxc_parser::Parser::new(&self.allocator, self.source_text, self.source_type).parse();
@ -85,25 +146,11 @@ impl<'a> SemanticTester<'a> {
);
let program = self.allocator.alloc(parse.program);
let semantic_ret = SemanticBuilder::new(self.source_text, self.source_type)
SemanticBuilder::new(self.source_text, self.source_type)
.with_check_syntax_error(true)
.with_trivias(parse.trivias)
.with_cfg(self.cfg)
.build(program);
if !semantic_ret.errors.is_empty() {
let report = self.wrap_diagnostics(semantic_ret.errors);
panic!(
"Semantic analysis failed:\n\n{}",
report
.iter()
.map(ToString::to_string)
.intersperse("\n\n".to_owned())
.collect::<String>()
);
};
semantic_ret.semantic
.build(program)
}
pub fn basic_blocks_count(&self) -> usize {
@ -150,6 +197,25 @@ impl<'a> SemanticTester<'a> {
ClassTester::has_class(self.build(), name)
}
pub fn has_error(&self, message: &str) {
let SemanticBuilderReturn { errors, .. } = self.build_with_errors();
assert!(
!errors.is_empty(),
"Expected an error matching '{message}', but no errors were produced"
);
if errors.iter().any(|e| e.message.contains(message)) {
return;
}
let num_errors = errors.len();
let rendered_errors =
self.wrap_diagnostics(errors).into_iter().map(|e| e.to_string()).join("\n\n");
panic!(
"Expected an error containing '{message}', but none of the {num_errors} matched:\n\n{rendered_errors}",
)
}
/// Finds some symbol by name in the source code.
///
/// ## Fails

View file

@ -3,7 +3,7 @@ commit: 12619ffe
parser_babel Summary:
AST Parsed : 2095/2101 (99.71%)
Positive Passed: 2087/2101 (99.33%)
Negative Passed: 1362/1501 (90.74%)
Negative Passed: 1364/1501 (90.87%)
Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js"
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions/input.js"
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js"
@ -96,8 +96,6 @@ Expect Syntax Error: "typescript/import/equals-in-script/input.ts"
Expect Syntax Error: "typescript/import/equals-require-in-script/input.ts"
Expect Syntax Error: "typescript/import/export-import-type/input.ts"
Expect Syntax Error: "typescript/import/type-equals/input.ts"
Expect Syntax Error: "typescript/interface/abstract/input.ts"
Expect Syntax Error: "typescript/interface/export-abstract-interface/input.ts"
Expect Syntax Error: "typescript/interface/get-set-invalid-optional-parameter/input.ts"
Expect Syntax Error: "typescript/interface/get-set-invalid-optional-parameter-babel-7/input.ts"
Expect Syntax Error: "typescript/interface/get-set-invalid-parameters/input.ts"
@ -10139,6 +10137,13 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts"
· ──
╰────
× Modifiers cannot be used here.
╭─[typescript/interface/abstract/input.ts:1:1]
1 │ abstract interface Foo {
· ────────
2 │ foo: string;
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[typescript/interface/declare-new-line/input.ts:1:8]
1 │ declare interface
@ -10147,6 +10152,13 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts"
╰────
help: Try insert a semicolon here
× Modifiers cannot be used here.
╭─[typescript/interface/export-abstract-interface/input.ts:1:8]
1 │ export abstract interface I {
· ────────
2 │
╰────
× Unexpected token
╭─[typescript/interface/export-default/input.ts:1:26]
1 │ export default interface {}

View file

@ -3,7 +3,7 @@ commit: d8086f14
parser_typescript Summary:
AST Parsed : 5280/5283 (99.94%)
Positive Passed: 5273/5283 (99.81%)
Negative Passed: 1053/4875 (21.60%)
Negative Passed: 1073/4875 (22.01%)
Expect Syntax Error: "compiler/ClassDeclaration10.ts"
Expect Syntax Error: "compiler/ClassDeclaration11.ts"
Expect Syntax Error: "compiler/ClassDeclaration13.ts"
@ -652,7 +652,6 @@ Expect Syntax Error: "compiler/exhaustiveSwitchCheckCircularity.ts"
Expect Syntax Error: "compiler/exhaustiveSwitchImplicitReturn.ts"
Expect Syntax Error: "compiler/expandoFunctionContextualTypesNoValue.ts"
Expect Syntax Error: "compiler/expandoFunctionNestedAssigments.ts"
Expect Syntax Error: "compiler/exportAlreadySeen.ts"
Expect Syntax Error: "compiler/exportAsNamespaceConflict.ts"
Expect Syntax Error: "compiler/exportAssignmentWithExports.ts"
Expect Syntax Error: "compiler/exportDeclarationsInAmbientNamespaces2.ts"
@ -755,7 +754,6 @@ Expect Syntax Error: "compiler/functionTypeArgumentArityErrors.ts"
Expect Syntax Error: "compiler/functionTypeArgumentAssignmentCompat.ts"
Expect Syntax Error: "compiler/functionVariableInReturnTypeAnnotation.ts"
Expect Syntax Error: "compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts"
Expect Syntax Error: "compiler/functionsWithModifiersInBlocks1.ts"
Expect Syntax Error: "compiler/fuzzy.ts"
Expect Syntax Error: "compiler/generatorES6_5.ts"
Expect Syntax Error: "compiler/generatorReturnExpressionIsChecked.ts"
@ -1409,7 +1407,6 @@ Expect Syntax Error: "compiler/primitiveTypeAsInterfaceName.ts"
Expect Syntax Error: "compiler/primitiveTypeAsInterfaceNameGeneric.ts"
Expect Syntax Error: "compiler/primitiveTypeAssignment.ts"
Expect Syntax Error: "compiler/privacyGloImportParseErrors.ts"
Expect Syntax Error: "compiler/privacyImportParseErrors.ts"
Expect Syntax Error: "compiler/privateAccessInSubclass1.ts"
Expect Syntax Error: "compiler/privateFieldAssignabilityFromUnknown.ts"
Expect Syntax Error: "compiler/privateInterfaceProperties.ts"
@ -1943,11 +1940,7 @@ Expect Syntax Error: "conformance/async/es5/asyncArrowFunction/asyncArrowFunctio
Expect Syntax Error: "conformance/async/es5/asyncArrowFunction/asyncArrowFunction3_es5.ts"
Expect Syntax Error: "conformance/async/es5/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es5.ts"
Expect Syntax Error: "conformance/async/es5/asyncAwaitIsolatedModules_es5.ts"
Expect Syntax Error: "conformance/async/es5/asyncClass_es5.ts"
Expect Syntax Error: "conformance/async/es5/asyncDeclare_es5.ts"
Expect Syntax Error: "conformance/async/es5/asyncEnum_es5.ts"
Expect Syntax Error: "conformance/async/es5/asyncInterface_es5.ts"
Expect Syntax Error: "conformance/async/es5/asyncModule_es5.ts"
Expect Syntax Error: "conformance/async/es5/functionDeclarations/asyncFunctionDeclaration13_es5.ts"
Expect Syntax Error: "conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts"
Expect Syntax Error: "conformance/async/es5/functionDeclarations/asyncFunctionDeclaration3_es5.ts"
@ -1956,11 +1949,7 @@ Expect Syntax Error: "conformance/async/es5/functionDeclarations/asyncFunctionDe
Expect Syntax Error: "conformance/async/es6/asyncArrowFunction/asyncArrowFunction10_es6.ts"
Expect Syntax Error: "conformance/async/es6/asyncArrowFunction/asyncArrowFunction3_es6.ts"
Expect Syntax Error: "conformance/async/es6/asyncAwaitIsolatedModules_es6.ts"
Expect Syntax Error: "conformance/async/es6/asyncClass_es6.ts"
Expect Syntax Error: "conformance/async/es6/asyncDeclare_es6.ts"
Expect Syntax Error: "conformance/async/es6/asyncEnum_es6.ts"
Expect Syntax Error: "conformance/async/es6/asyncInterface_es6.ts"
Expect Syntax Error: "conformance/async/es6/asyncModule_es6.ts"
Expect Syntax Error: "conformance/async/es6/asyncQualifiedReturnType_es6.ts"
Expect Syntax Error: "conformance/async/es6/await_unaryExpression_es6_1.ts"
Expect Syntax Error: "conformance/async/es6/await_unaryExpression_es6_2.ts"
@ -1994,7 +1983,6 @@ Expect Syntax Error: "conformance/classes/classDeclarations/classAbstractKeyword
Expect Syntax Error: "conformance/classes/classDeclarations/classAbstractKeyword/classAbstractSuperCalls.ts"
Expect Syntax Error: "conformance/classes/classDeclarations/classAbstractKeyword/classAbstractUsingAbstractMethod1.ts"
Expect Syntax Error: "conformance/classes/classDeclarations/classAbstractKeyword/classAbstractUsingAbstractMethods2.ts"
Expect Syntax Error: "conformance/classes/classDeclarations/classAbstractKeyword/classAbstractWithInterface.ts"
Expect Syntax Error: "conformance/classes/classDeclarations/classAndInterfaceMergeConflictingMembers.ts"
Expect Syntax Error: "conformance/classes/classDeclarations/classExtendingClassLikeType.ts"
Expect Syntax Error: "conformance/classes/classDeclarations/classExtendingNonConstructor.ts"
@ -2853,8 +2841,6 @@ Expect Syntax Error: "conformance/internalModules/exportDeclarations/ModuleWithE
Expect Syntax Error: "conformance/internalModules/importDeclarations/circularImportAlias.ts"
Expect Syntax Error: "conformance/internalModules/importDeclarations/invalidImportAliasIdentifiers.ts"
Expect Syntax Error: "conformance/internalModules/importDeclarations/shadowedInternalModule.ts"
Expect Syntax Error: "conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts"
Expect Syntax Error: "conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts"
Expect Syntax Error: "conformance/internalModules/moduleDeclarations/InvalidNonInstantiatedModule.ts"
Expect Syntax Error: "conformance/internalModules/moduleDeclarations/invalidNestedModules.ts"
Expect Syntax Error: "conformance/jsdoc/assertionsAndNonReturningFunctions.ts"
@ -3157,9 +3143,6 @@ Expect Syntax Error: "conformance/parser/ecmascript5/IndexSignatures/parserIndex
Expect Syntax Error: "conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature5.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration1.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration2.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration3.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration4.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration6.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration8.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessor1.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration1.ts"
@ -3192,8 +3175,6 @@ Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParame
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList2.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList7.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/ParameterLists/parserParameterList8.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected1.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected2.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected4.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected6.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/Protected/Protected7.ts"
@ -3205,7 +3186,6 @@ Expect Syntax Error: "conformance/parser/ecmascript5/RegressionTests/parser50969
Expect Syntax Error: "conformance/parser/ecmascript5/RegressionTests/parser509698.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/RegressionTests/parser536727.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/RegressionTests/parser579071.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/RegressionTests/parser618973.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/RegressionTests/parserTernaryAndCommaOperators1.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts"
Expect Syntax Error: "conformance/parser/ecmascript5/RegularExpressions/parserRegularExpression2.ts"
@ -6434,6 +6414,86 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
· ╰── `from` expected
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:2:12]
1 │ module M {
2 │ export export var x = 1;
· ──────
3 │ export export function f() { }
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:3:12]
2 │ export export var x = 1;
3 │ export export function f() { }
· ──────
4 │
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:6:16]
5 │ export export module N {
6 │ export export class C { }
· ──────
7 │ export export interface I { }
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:7:16]
6 │ export export class C { }
7 │ export export interface I { }
· ──────
8 │ }
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:5:12]
4 │
5 │ export export module N {
· ──────
6 │ export export class C { }
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:12:12]
11 │ declare module A {
12 │ export export var x;
· ──────
13 │ export export function f()
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:13:12]
12 │ export export var x;
13 │ export export function f()
· ──────
14 │
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:16:16]
15 │ export export module N {
16 │ export export class C { }
· ──────
17 │ export export interface I { }
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:17:16]
16 │ export export class C { }
17 │ export export interface I { }
· ──────
18 │ }
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:15:12]
14 │
15 │ export export module N {
· ──────
16 │ export export class C { }
╰────
× Unexpected token
╭─[compiler/exportAssignmentWithDeclareAndExportModifiers.ts:2:16]
1 │ var x;
@ -6683,6 +6743,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
154 │ }
╰────
× Modifiers cannot be used here.
╭─[compiler/functionsWithModifiersInBlocks1.ts:4:12]
3 │ export function f() { }
4 │ declare export function f() { }
· ──────
5 │ }
╰────
× Unexpected token
╭─[compiler/genericCallWithoutArgs.ts:4:18]
3 │
@ -8629,6 +8697,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
1 │ if (true) {
╰────
× Modifiers cannot be used here.
╭─[compiler/privacyImportParseErrors.ts:326:9]
325 │
326 │ declare export module "anotherParseError2" {
· ──────
327 │ module m2 {
╰────
× Unexpected token
╭─[compiler/privateNameJsx.tsx:4:22]
3 │ render() {
@ -10592,6 +10668,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
2 │ }
╰────
× 'async' modifier cannot be used here.
╭─[conformance/async/es5/asyncClass_es5.ts:1:1]
1 │ async class C {
· ─────
2 │ }
╰────
× Constructor can't be an async method
╭─[conformance/async/es5/asyncConstructor_es5.ts:2:9]
1 │ class C {
@ -10600,6 +10683,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ }
╰────
× 'async' modifier cannot be used here.
╭─[conformance/async/es5/asyncEnum_es5.ts:1:1]
1 │ async enum E {
· ─────
2 │ Value
╰────
× Expected `(` but found `Identifier`
╭─[conformance/async/es5/asyncGetter_es5.ts:2:13]
1 │ class C {
@ -10609,6 +10699,20 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ }
╰────
× 'async' modifier cannot be used here.
╭─[conformance/async/es5/asyncInterface_es5.ts:1:1]
1 │ async interface I {
· ─────
2 │ }
╰────
× 'async' modifier cannot be used here.
╭─[conformance/async/es5/asyncModule_es5.ts:1:1]
1 │ async module M {
· ─────
2 │ }
╰────
× Expected `(` but found `Identifier`
╭─[conformance/async/es5/asyncSetter_es5.ts:2:13]
1 │ class C {
@ -10699,6 +10803,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
2 │ }
╰────
× 'async' modifier cannot be used here.
╭─[conformance/async/es6/asyncClass_es6.ts:1:1]
1 │ async class C {
· ─────
2 │ }
╰────
× Constructor can't be an async method
╭─[conformance/async/es6/asyncConstructor_es6.ts:2:9]
1 │ class C {
@ -10707,6 +10818,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ }
╰────
× 'async' modifier cannot be used here.
╭─[conformance/async/es6/asyncEnum_es6.ts:1:1]
1 │ async enum E {
· ─────
2 │ Value
╰────
× Expected `(` but found `Identifier`
╭─[conformance/async/es6/asyncGetter_es6.ts:2:13]
1 │ class C {
@ -10716,6 +10834,20 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ }
╰────
× 'async' modifier cannot be used here.
╭─[conformance/async/es6/asyncInterface_es6.ts:1:1]
1 │ async interface I {
· ─────
2 │ }
╰────
× 'async' modifier cannot be used here.
╭─[conformance/async/es6/asyncModule_es6.ts:1:1]
1 │ async module M {
· ─────
2 │ }
╰────
× Expected `(` but found `Identifier`
╭─[conformance/async/es6/asyncSetter_es6.ts:2:13]
1 │ class C {
@ -10873,6 +11005,12 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
17 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/classes/classDeclarations/classAbstractKeyword/classAbstractWithInterface.ts:1:1]
1 │ abstract interface I {}
· ────────
╰────
× Identifier `C` has already been declared
╭─[conformance/classes/classDeclarations/classAndVariableWithSameName.ts:1:7]
1 │ class C { foo: string; } // error
@ -16067,6 +16205,222 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ let;
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:4:5]
3 │ module Y {
4 │ public class A { s: string }
· ──────
5 │
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:6:5]
5 │
6 │ public class BB<T> extends A {
· ──────
7 │ id: number;
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:12:5]
11 │ module Y2 {
12 │ public class AA<T> { s: T }
· ──────
13 │ public interface I { id: number }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:13:5]
12 │ public class AA<T> { s: T }
13 │ public interface I { id: number }
· ──────
14 │
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:15:5]
14 │
15 │ public class B extends AA<string> implements I { id: number }
· ──────
16 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:19:5]
18 │ module Y3 {
19 │ public module Module {
· ──────
20 │ class A { s: string }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:25:5]
24 │ module Y4 {
25 │ public enum Color { Blue, Red }
· ──────
26 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:29:5]
28 │ module YY {
29 │ private class A { s: string }
· ───────
30 │
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:31:5]
30 │
31 │ private class BB<T> extends A {
· ───────
32 │ id: number;
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:37:5]
36 │ module YY2 {
37 │ private class AA<T> { s: T }
· ───────
38 │ private interface I { id: number }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:38:5]
37 │ private class AA<T> { s: T }
38 │ private interface I { id: number }
· ───────
39 │
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:40:5]
39 │
40 │ private class B extends AA<string> implements I { id: number }
· ───────
41 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:44:5]
43 │ module YY3 {
44 │ private module Module {
· ───────
45 │ class A { s: string }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:50:5]
49 │ module YY4 {
50 │ private enum Color { Blue, Red }
· ───────
51 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:55:5]
54 │ module YYY {
55 │ static class A { s: string }
· ──────
56 │
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:57:5]
56 │
57 │ static class BB<T> extends A {
· ──────
58 │ id: number;
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:63:5]
62 │ module YYY2 {
63 │ static class AA<T> { s: T }
· ──────
64 │ static interface I { id: number }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:64:5]
63 │ static class AA<T> { s: T }
64 │ static interface I { id: number }
· ──────
65 │
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:66:5]
65 │
66 │ static class B extends AA<string> implements I { id: number }
· ──────
67 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:70:5]
69 │ module YYY3 {
70 │ static module Module {
· ──────
71 │ class A { s: string }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithStatementsOfEveryKind.ts:76:5]
75 │ module YYY4 {
76 │ static enum Color { Blue, Red }
· ──────
77 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:4:5]
3 │ module Y {
4 │ public var x: number = 0;
· ──────
5 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:8:5]
7 │ module Y2 {
8 │ public function fn(x: string) { }
· ──────
9 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:12:5]
11 │ module Y4 {
12 │ static var x: number = 0;
· ──────
13 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:16:5]
15 │ module YY {
16 │ static function fn(x: string) { }
· ──────
17 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:20:5]
19 │ module YY2 {
20 │ private var x: number = 0;
· ───────
21 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:25:5]
24 │ module YY3 {
25 │ private function fn(x: string) { }
· ───────
26 │ }
╰────
× Identifier `Point` has already been declared
╭─[conformance/internalModules/moduleDeclarations/invalidInstantiatedModule.ts:2:18]
1 │ module M {
@ -17154,6 +17508,27 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration3.ts:1:1]
1 │ public interface I {
· ──────
2 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration4.ts:1:1]
1 │ static interface I {
· ──────
2 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/parser/ecmascript5/InterfaceDeclarations/parserInterfaceDeclaration6.ts:1:8]
1 │ export export interface I {
· ──────
2 │ }
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration10.ts:2:11]
1 │ class C {
@ -17376,6 +17751,20 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/parser/ecmascript5/Protected/Protected1.ts:1:1]
1 │ protected class C {
· ─────────
2 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/parser/ecmascript5/Protected/Protected2.ts:1:1]
1 │ protected module M {
· ─────────
2 │ }
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[conformance/parser/ecmascript5/RealWorld/parserharness.ts:1430:16]
1429 │ // Regex for parsing options in the format "@Alpha: Value of any sort"
@ -17466,6 +17855,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
╰────
help: Try insert a semicolon here
× Modifiers cannot be used here.
╭─[conformance/parser/ecmascript5/RegressionTests/parser618973.ts:1:8]
1 │ export export class Foo {
· ──────
2 │ public Bar() {
╰────
× The keyword 'static' is reserved
╭─[conformance/parser/ecmascript5/RegressionTests/parser642331.ts:2:18]
1 │ class test {