refactor(ast)!: replace Modifiers with declare on VariableDeclaration (#3839)

part of #2958
This commit is contained in:
Boshen 2024-06-23 10:34:52 +00:00
parent f029273b04
commit 9b38119ec9
25 changed files with 224 additions and 200 deletions

View file

@ -1,7 +1,6 @@
// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
#![allow(non_snake_case)]
use crate::ast::*;
use std::cell::Cell;
use oxc_allocator::{Box, Vec};
@ -17,6 +16,7 @@ use oxc_syntax::{
};
use super::macros::inherit_variants;
use super::*;
#[cfg(feature = "serialize")]
use serde::Serialize;
@ -1000,8 +1000,7 @@ pub struct VariableDeclaration<'a> {
pub span: Span,
pub kind: VariableDeclarationKind,
pub declarations: Vec<'a, VariableDeclarator<'a>>,
/// Valid Modifiers: `export`, `declare`
pub modifiers: Modifiers<'a>,
pub declare: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

View file

@ -1,3 +1,5 @@
// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
#![allow(non_snake_case)]
//! AST Definitions
//!
//! # Enum inheritance
@ -181,3 +183,128 @@ mod ts;
use macros::inherit_variants;
pub use self::{js::*, jsx::*, literal::*, ts::*};
#[cfg(feature = "serialize")]
use serde::Serialize;
#[cfg(feature = "serialize")]
use tsify::Tsify;
use oxc_allocator::Vec;
use oxc_span::Span;
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct Modifier {
#[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span,
pub kind: ModifierKind,
}
#[derive(Debug, Default, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(transparent))]
pub struct Modifiers<'a>(Option<Vec<'a, Modifier>>);
impl<'a> Modifiers<'a> {
pub fn new(modifiers: Vec<'a, Modifier>) -> Self {
Self(Some(modifiers))
}
pub fn empty() -> Self {
Self(None)
}
pub fn is_none(&self) -> bool {
self.0.is_none()
}
pub fn contains(&self, target: ModifierKind) -> bool {
self.0
.as_ref()
.map_or(false, |modifiers| modifiers.iter().any(|modifier| modifier.kind == target))
}
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,
{
self.0.as_ref().and_then(|modifiers| modifiers.iter().find(|modifier| f(modifier)))
}
pub fn is_contains_declare(&self) -> bool {
self.contains(ModifierKind::Declare)
}
pub fn is_contains_abstract(&self) -> bool {
self.contains(ModifierKind::Abstract)
}
pub fn remove_type_modifiers(&mut self) {
if let Some(list) = &mut self.0 {
list.retain(|m| !m.kind.is_typescript_syntax());
}
}
pub fn add_modifier(&mut self, modifier: Modifier) {
if let Some(list) = self.0.as_mut() {
list.push(modifier);
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
pub enum ModifierKind {
Abstract,
Accessor,
Async,
Const,
Declare,
Default,
Export,
In,
Public,
Private,
Protected,
Readonly,
Static,
Out,
Override,
}
impl ModifierKind {
pub fn is_typescript_syntax(&self) -> bool {
!matches!(self, Self::Async | Self::Default | Self::Export | Self::Static)
}
pub fn as_str(self) -> &'static str {
match self {
Self::Abstract => "abstract",
Self::Accessor => "accessor",
Self::Async => "async",
Self::Const => "const",
Self::Declare => "declare",
Self::Default => "default",
Self::Export => "export",
Self::In => "in",
Self::Public => "public",
Self::Private => "private",
Self::Protected => "protected",
Self::Readonly => "readonly",
Self::Static => "static",
Self::Out => "out",
Self::Override => "override",
}
}
}

View file

@ -20,7 +20,7 @@ use serde::Serialize;
#[cfg(feature = "serialize")]
use tsify::Tsify;
use super::{inherit_variants, js::*, jsx::*, literal::*};
use super::{inherit_variants, js::*, jsx::*, literal::*, Modifiers};
#[cfg(feature = "serialize")]
#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)]
@ -1094,41 +1094,6 @@ pub struct Decorator<'a> {
pub expression: Expression<'a>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
pub enum ModifierKind {
Abstract,
Accessor,
Async,
Const,
Declare,
Default,
Export,
In,
Public,
Private,
Protected,
Readonly,
Static,
Out,
Override,
}
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct Modifier {
#[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span,
pub kind: ModifierKind,
}
#[derive(Debug, Default, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(transparent))]
pub struct Modifiers<'a>(pub(crate) Option<Vec<'a, Modifier>>);
/// Export Assignment in non-module files
///
/// `export = foo`

View file

@ -111,7 +111,7 @@ impl<'a> AstBuilder<'a> {
Span::default(),
VariableDeclarationKind::Var,
self.new_vec(),
Modifiers::empty(),
false,
);
let empty_decl = Declaration::VariableDeclaration(empty_decl);
mem::replace(decl, empty_decl)
@ -1167,9 +1167,9 @@ impl<'a> AstBuilder<'a> {
span: Span,
kind: VariableDeclarationKind,
declarations: Vec<'a, VariableDeclarator<'a>>,
modifiers: Modifiers<'a>,
declare: bool,
) -> Box<'a, VariableDeclaration<'a>> {
self.alloc(VariableDeclaration { span, kind, declarations, modifiers })
self.alloc(VariableDeclaration { span, kind, declarations, declare })
}
#[inline]

View file

@ -705,23 +705,23 @@ impl<'a> Declaration<'a> {
}
}
pub fn modifiers(&self) -> Option<&Modifiers<'a>> {
pub fn declare(&self) -> bool {
match self {
Declaration::VariableDeclaration(decl) => Some(&decl.modifiers),
Declaration::FunctionDeclaration(decl) => Some(&decl.modifiers),
Declaration::ClassDeclaration(decl) => Some(&decl.modifiers),
Declaration::TSEnumDeclaration(decl) => Some(&decl.modifiers),
Declaration::TSTypeAliasDeclaration(decl) => Some(&decl.modifiers),
Declaration::TSModuleDeclaration(decl) => Some(&decl.modifiers),
Declaration::TSInterfaceDeclaration(decl) => Some(&decl.modifiers),
_ => None,
Declaration::VariableDeclaration(decl) => decl.declare,
Declaration::FunctionDeclaration(decl) => decl.modifiers.is_contains_declare(),
Declaration::ClassDeclaration(decl) => decl.modifiers.is_contains_declare(),
Declaration::TSEnumDeclaration(decl) => decl.modifiers.is_contains_declare(),
Declaration::TSTypeAliasDeclaration(decl) => decl.modifiers.is_contains_declare(),
Declaration::TSModuleDeclaration(decl) => decl.modifiers.is_contains_declare(),
Declaration::TSInterfaceDeclaration(decl) => decl.modifiers.is_contains_declare(),
_ => false,
}
}
}
impl<'a> VariableDeclaration<'a> {
pub fn is_typescript_syntax(&self) -> bool {
self.modifiers.contains(ModifierKind::Declare)
self.declare
}
pub fn has_init(&self) -> bool {

View file

@ -6,13 +6,14 @@
// NB: `#[visited_node]` attribute on AST nodes does not do anything to the code in this file.
// It is purely a marker for codegen used in `oxc_traverse`. See docs in that crate.
use crate::ast::*;
use std::{cell::Cell, hash::Hash};
use oxc_allocator::Vec;
use oxc_span::{Atom, GetSpan, Span};
use crate::ast::Modifiers;
use crate::ast::*;
impl<'a> TSEnumDeclaration<'a> {
pub fn new(
span: Span,
@ -198,68 +199,6 @@ impl<'a> Decorator<'a> {
}
}
impl ModifierKind {
pub fn is_typescript_syntax(&self) -> bool {
!matches!(self, Self::Async | Self::Default | Self::Export | Self::Static)
}
}
impl<'a> Modifiers<'a> {
pub fn new(modifiers: Vec<'a, Modifier>) -> Self {
Self(Some(modifiers))
}
pub fn empty() -> Self {
Self(None)
}
pub fn is_none(&self) -> bool {
self.0.is_none()
}
pub fn contains(&self, target: ModifierKind) -> bool {
self.0
.as_ref()
.map_or(false, |modifiers| modifiers.iter().any(|modifier| modifier.kind == target))
}
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,
{
self.0.as_ref().and_then(|modifiers| modifiers.iter().find(|modifier| f(modifier)))
}
pub fn is_contains_declare(&self) -> bool {
self.contains(ModifierKind::Declare)
}
pub fn is_contains_abstract(&self) -> bool {
self.contains(ModifierKind::Abstract)
}
pub fn remove_type_modifiers(&mut self) {
if let Some(list) = &mut self.0 {
list.retain(|m| !m.kind.is_typescript_syntax());
}
}
pub fn add_modifier(&mut self, modifier: Modifier) {
if let Some(list) = self.0.as_mut() {
list.push(modifier);
}
}
}
impl ImportOrExportKind {
pub fn is_value(&self) -> bool {
matches!(self, Self::Value)

View file

@ -580,7 +580,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for UsingDeclaration<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for VariableDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start);
if self.modifiers.is_contains_declare() {
if self.declare {
p.print_str(b"declare ");
}

View file

@ -19,7 +19,7 @@ impl<'a> IsolatedDeclarations<'a> {
decl: &VariableDeclaration<'a>,
check_binding: bool,
) -> Option<Box<'a, VariableDeclaration<'a>>> {
if decl.modifiers.is_contains_declare() {
if decl.declare {
None
} else {
let declarations =
@ -39,7 +39,7 @@ impl<'a> IsolatedDeclarations<'a> {
decl.span,
decl.kind,
self.ast.new_vec_from_iter(declarations),
self.modifiers_declare(),
self.modifiers_declare().is_contains_declare(),
)
}
@ -126,7 +126,7 @@ impl<'a> IsolatedDeclarations<'a> {
decl.span,
VariableDeclarationKind::Const,
declarations,
self.modifiers_declare(),
self.modifiers_declare().is_contains_declare(),
)
}

View file

@ -75,7 +75,7 @@ impl<'a> IsolatedDeclarations<'a> {
span: SPAN,
kind,
declarations,
modifiers: self.modifiers_declare(),
declare: self.modifiers_declare().is_contains_declare(),
}),
ExportDefaultDeclarationKind::from(
self.ast.identifier_reference_expression(

View file

@ -408,3 +408,11 @@ pub fn jsx_element_no_match(span0: Span, span1: Span, name: &str) -> OxcDiagnost
OxcDiagnostic::error(format!("Expected corresponding JSX closing tag for '{name}'."))
.with_labels([span0.into(), span1.into()])
}
#[cold]
pub fn modifiers_cannot_appear(span: Span, name: &str) -> OxcDiagnostic {
OxcDiagnostic::error(format!(
"TS1044: '{name}' modifier cannot appear on a module or namespace element."
))
.with_label(span)
}

View file

@ -41,7 +41,7 @@ impl<'a> ParserImpl<'a> {
&mut self,
start_span: Span,
decl_ctx: VariableDeclarationContext,
modifiers: Modifiers<'a>,
modifiers: &Modifiers<'a>,
) -> Result<Box<'a, VariableDeclaration<'a>>> {
let kind = match self.cur_kind() {
Kind::Var => VariableDeclarationKind::Var,
@ -67,7 +67,21 @@ impl<'a> ParserImpl<'a> {
self.asi()?;
}
Ok(self.ast.variable_declaration(self.end_span(start_span), kind, declarations, modifiers))
for modifier in modifiers.iter() {
if modifier.kind != ModifierKind::Declare {
self.error(diagnostics::modifiers_cannot_appear(
modifier.span,
modifier.kind.as_str(),
));
}
}
Ok(self.ast.variable_declaration(
self.end_span(start_span),
kind,
declarations,
modifiers.is_contains_declare(),
))
}
fn parse_variable_declarator(

View file

@ -160,7 +160,7 @@ impl<'a> ParserImpl<'a> {
let decl = self.parse_variable_declaration(
start_span,
VariableDeclarationContext::new(VariableDeclarationParent::Statement),
Modifiers::empty(),
&Modifiers::empty(),
)?;
if stmt_ctx.is_single_statement() && decl.kind.is_lexical() {
@ -287,7 +287,7 @@ impl<'a> ParserImpl<'a> {
let start_span = self.start_span();
let init_declaration = self.context(Context::empty(), Context::In, |p| {
let decl_ctx = VariableDeclarationContext::new(VariableDeclarationParent::For);
p.parse_variable_declaration(start_span, decl_ctx, Modifiers::empty())
p.parse_variable_declaration(start_span, decl_ctx, &Modifiers::empty())
})?;
// for (.. a in) for (.. a of)

View file

@ -304,7 +304,7 @@ impl<'a> ParserImpl<'a> {
.parse_variable_declaration(
start_span,
VariableDeclarationContext::new(VariableDeclarationParent::Clause),
modifiers,
&modifiers,
)
.map(Declaration::VariableDeclaration),
_ if self.at_function_with_async() => {

View file

@ -94,7 +94,6 @@ 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) => {

View file

@ -172,13 +172,6 @@ fn check_declaration_modifiers<'a>(
}
}
}
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);

View file

@ -114,20 +114,3 @@ 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

@ -131,7 +131,7 @@ impl<'a> ArrowFunctions<'a> {
SPAN,
VariableDeclarationKind::Var,
self.ctx.ast.new_vec_single(variable_declarator),
Modifiers::empty(),
false,
);
let stmt = Statement::VariableDeclaration(stmt);

View file

@ -141,7 +141,7 @@ impl<'a> ModuleImports<'a> {
let decl = self.ast.variable_declarator(SPAN, var_kind, id, Some(init), false);
self.ast.new_vec_single(decl)
};
let var_decl = self.ast.variable_declaration(SPAN, var_kind, decl, Modifiers::empty());
let var_decl = self.ast.variable_declaration(SPAN, var_kind, decl, false);
Statement::VariableDeclaration(var_decl)
}
}

View file

@ -160,7 +160,7 @@ impl<'a> ReactJsxSource<'a> {
let decl = self.ctx.ast.variable_declarator(SPAN, var_kind, id, Some(init), false);
self.ctx.ast.new_vec_single(decl)
};
let var_decl = self.ctx.ast.variable_declaration(SPAN, var_kind, decl, Modifiers::empty());
let var_decl = self.ctx.ast.variable_declaration(SPAN, var_kind, decl, false);
Some(Statement::VariableDeclaration(var_decl))
}

View file

@ -311,13 +311,15 @@ impl<'a> TypeScriptAnnotations<'a> {
pub fn transform_statements(&mut self, stmts: &mut ArenaVec<'a, Statement<'a>>) {
// Remove declare declaration
stmts.retain(|stmt| {
if let Some(decl) = stmt.as_declaration() {
decl.modifiers().map_or(true, |m| !m.is_contains_declare())
} else {
true
}
});
stmts.retain(
|stmt| {
if let Some(decl) = stmt.as_declaration() {
!decl.declare()
} else {
true
}
},
);
}
pub fn transform_statements_on_exit(

View file

@ -134,8 +134,7 @@ impl<'a> TypeScriptEnum<'a> {
decls.push(decl);
decls
};
let variable_declaration =
self.ctx.ast.variable_declaration(span, kind, decls, Modifiers::empty());
let variable_declaration = self.ctx.ast.variable_declaration(span, kind, decls, false);
let variable_declaration = Declaration::VariableDeclaration(variable_declaration);
let stmt = if is_export {

View file

@ -66,8 +66,7 @@ impl<'a> TypeScript<'a> {
false,
))
};
let variable_declaration =
self.ctx.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty());
let variable_declaration = self.ctx.ast.variable_declaration(SPAN, kind, decls, false);
Declaration::VariableDeclaration(variable_declaration)
}

View file

@ -190,7 +190,7 @@ impl<'a> TypeScript<'a> {
// legal syntax in TS namespaces
let export_decl = export_decl.unbox();
if let Some(decl) = export_decl.declaration {
if decl.modifiers().is_some_and(Modifiers::is_contains_declare) {
if decl.declare() {
continue;
}
match decl {
@ -290,7 +290,7 @@ impl<'a> TypeScript<'a> {
SPAN,
kind,
declarations,
Modifiers::empty(),
false,
))
}

View file

@ -3835,8 +3835,8 @@ pub(crate) const OFFSET_VARIABLE_DECLARATION_SPAN: usize = offset_of!(VariableDe
pub(crate) const OFFSET_VARIABLE_DECLARATION_KIND: usize = offset_of!(VariableDeclaration, kind);
pub(crate) const OFFSET_VARIABLE_DECLARATION_DECLARATIONS: usize =
offset_of!(VariableDeclaration, declarations);
pub(crate) const OFFSET_VARIABLE_DECLARATION_MODIFIERS: usize =
offset_of!(VariableDeclaration, modifiers);
pub(crate) const OFFSET_VARIABLE_DECLARATION_DECLARE: usize =
offset_of!(VariableDeclaration, declare);
#[repr(transparent)]
#[derive(Debug)]
@ -3857,11 +3857,8 @@ impl<'a> VariableDeclarationWithoutDeclarations<'a> {
}
#[inline]
pub fn modifiers(&self) -> &Modifiers<'a> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_VARIABLE_DECLARATION_MODIFIERS)
as *const Modifiers<'a>)
}
pub fn declare(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_VARIABLE_DECLARATION_DECLARE) as *const bool) }
}
}

View file

@ -6414,7 +6414,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
· ╰── `from` expected
╰────
× Modifiers cannot be used here.
× TS1044: 'export' modifier cannot appear on a module or namespace element.
╭─[compiler/exportAlreadySeen.ts:2:12]
1 │ module M {
2 │ export export var x = 1;
@ -6422,6 +6422,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ export export function f() { }
╰────
× TS1044: 'export' modifier cannot appear on a module or namespace element.
╭─[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:3:12]
2 │ export export var x = 1;
@ -6454,14 +6462,6 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
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;
@ -16373,7 +16373,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
77 │ }
╰────
× Modifiers cannot be used here.
× TS1044: 'public' modifier cannot appear on a module or namespace element.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:4:5]
3 │ module Y {
4 │ public var x: number = 0;
@ -16381,6 +16381,22 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
5 │ }
╰────
× TS1044: 'static' modifier cannot appear on a module or namespace element.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:12:5]
11 │ module Y4 {
12 │ static var x: number = 0;
· ──────
13 │ }
╰────
× TS1044: 'private' modifier cannot appear on a module or namespace element.
╭─[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:8:5]
7 │ module Y2 {
@ -16389,14 +16405,6 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
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 {
@ -16405,14 +16413,6 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
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 {