mirror of
https://github.com/swc-project/swc.git
synced 2024-10-05 12:49:21 +03:00
fix(es/parser): Emit an error for multiple constructors with body (#4031)
This commit is contained in:
parent
60df339915
commit
120d2a534e
@ -169,6 +169,7 @@ pub enum SyntaxError {
|
|||||||
PrivateNameModifier(JsWord),
|
PrivateNameModifier(JsWord),
|
||||||
ReadOnlyMethod,
|
ReadOnlyMethod,
|
||||||
GeneratorConstructor,
|
GeneratorConstructor,
|
||||||
|
DuplicateConstructor,
|
||||||
TsBindingPatCannotBeOptional,
|
TsBindingPatCannotBeOptional,
|
||||||
SuperCallOptional,
|
SuperCallOptional,
|
||||||
|
|
||||||
@ -422,6 +423,7 @@ impl SyntaxError {
|
|||||||
SyntaxError::PropertyNamedConstructor => {
|
SyntaxError::PropertyNamedConstructor => {
|
||||||
"Classes may not have a non-static field named 'constructor'".into()
|
"Classes may not have a non-static field named 'constructor'".into()
|
||||||
}
|
}
|
||||||
|
SyntaxError::DuplicateConstructor => "A class can only have one constructor".into(),
|
||||||
SyntaxError::PrivateNameModifier(modifier) => format!(
|
SyntaxError::PrivateNameModifier(modifier) => format!(
|
||||||
"'{}' modifier cannot be used with a private identifier",
|
"'{}' modifier cannot be used with a private identifier",
|
||||||
modifier
|
modifier
|
||||||
|
@ -316,6 +316,7 @@ impl<'a, I: Tokens> Parser<I> {
|
|||||||
|
|
||||||
fn parse_class_body(&mut self) -> PResult<Vec<ClassMember>> {
|
fn parse_class_body(&mut self) -> PResult<Vec<ClassMember>> {
|
||||||
let mut elems = vec![];
|
let mut elems = vec![];
|
||||||
|
let mut has_constructor_with_body = false;
|
||||||
while !eof!(self) && !is!(self, '}') {
|
while !eof!(self) && !is!(self, '}') {
|
||||||
if eat_exact!(self, ';') {
|
if eat_exact!(self, ';') {
|
||||||
let span = self.input.prev_span();
|
let span = self.input.prev_span();
|
||||||
@ -328,7 +329,22 @@ impl<'a, I: Tokens> Parser<I> {
|
|||||||
allow_direct_super: true,
|
allow_direct_super: true,
|
||||||
..self.ctx()
|
..self.ctx()
|
||||||
});
|
});
|
||||||
elems.push(p.parse_class_member()?);
|
let elem = p.parse_class_member()?;
|
||||||
|
|
||||||
|
if !p.ctx().in_declare {
|
||||||
|
if let ClassMember::Constructor(Constructor {
|
||||||
|
body: Some(..),
|
||||||
|
span,
|
||||||
|
..
|
||||||
|
}) = elem
|
||||||
|
{
|
||||||
|
if has_constructor_with_body {
|
||||||
|
p.emit_err(span, SyntaxError::DuplicateConstructor);
|
||||||
|
}
|
||||||
|
has_constructor_with_body = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elems.push(elem);
|
||||||
}
|
}
|
||||||
Ok(elems)
|
Ok(elems)
|
||||||
}
|
}
|
||||||
@ -706,6 +722,14 @@ impl<'a, I: Tokens> Parser<I> {
|
|||||||
let body: Option<_> =
|
let body: Option<_> =
|
||||||
self.parse_fn_body(false, false, params.is_simple_parameter_list())?;
|
self.parse_fn_body(false, false, params.is_simple_parameter_list())?;
|
||||||
|
|
||||||
|
if body.is_none() {
|
||||||
|
for param in params.iter() {
|
||||||
|
if param.is_ts_param_prop() {
|
||||||
|
self.emit_err(param.span(), SyntaxError::TS2369)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.syntax().typescript() && body.is_none() {
|
if self.syntax().typescript() && body.is_none() {
|
||||||
// Declare constructors cannot have assignment pattern in parameters
|
// Declare constructors cannot have assignment pattern in parameters
|
||||||
for p in ¶ms {
|
for p in ¶ms {
|
||||||
|
@ -10,3 +10,9 @@
|
|||||||
3 | constructor(override public v: string)
|
3 | constructor(override public v: string)
|
||||||
: ^^^^^^^^^^^^^^^^
|
: ^^^^^^^^^^^^^^^^
|
||||||
`----
|
`----
|
||||||
|
|
||||||
|
x A parameter property is only allowed in a constructor implementation
|
||||||
|
,-[$DIR/tests/typescript-errors/class/override-parameter-property/input.ts:3:3]
|
||||||
|
3 | constructor(override public v: string)
|
||||||
|
: ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
`----
|
||||||
|
@ -24,7 +24,6 @@ function charCode(s: string): number {
|
|||||||
|
|
||||||
export class TextProtoReader {
|
export class TextProtoReader {
|
||||||
constructor(readonly r: BufReader) { }
|
constructor(readonly r: BufReader) { }
|
||||||
constructor(readonly r: BufReader) { }
|
|
||||||
|
|
||||||
/** readLine() reads a single line from the TextProtoReader,
|
/** readLine() reads a single line from the TextProtoReader,
|
||||||
* eliding the final \n or \r\n from the returned string.
|
* eliding the final \n or \r\n from the returned string.
|
||||||
|
@ -354,9 +354,6 @@ function charCode(s) {
|
|||||||
return s.charCodeAt(0);
|
return s.charCodeAt(0);
|
||||||
}
|
}
|
||||||
class TextProtoReader {
|
class TextProtoReader {
|
||||||
constructor(r){
|
|
||||||
this.r = r;
|
|
||||||
}
|
|
||||||
constructor(r){
|
constructor(r){
|
||||||
this.r = r;
|
this.r = r;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user