refactor(parser): report this parameter error (#1788)

- follow up: #1728
This commit is contained in:
magic-akari 2023-12-23 22:09:14 +08:00 committed by GitHub
parent b25f014e84
commit 5b2696b711
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 22 deletions

View file

@ -257,6 +257,16 @@ pub struct GetterParameters(#[label] pub Span);
#[diagnostic()] #[diagnostic()]
pub struct SetterParameters(#[label] pub Span); pub struct SetterParameters(#[label] pub Span);
#[derive(Debug, Error, Diagnostic)]
#[error("TS2681: A constructor cannot have a `this` parameter.")]
#[diagnostic()]
pub struct TSConstructorThisParameter(#[label] pub Span);
#[derive(Debug, Error, Diagnostic)]
#[error("TS2730: An arrow function cannot have a `this` parameter.")]
#[diagnostic()]
pub struct TSArrowFunctionThisParameter(#[label] pub Span);
#[derive(Debug, Error, Diagnostic)] #[derive(Debug, Error, Diagnostic)]
#[error("'super' can only be used with function calls or in property accesses")] #[error("'super' can only be used with function calls or in property accesses")]
#[diagnostic(help("replace with `super()` or `super.prop` or `super[prop]`"))] #[diagnostic(help("replace with `super()` or `super.prop` or `super[prop]`"))]
@ -316,3 +326,8 @@ pub struct UsingDeclarationNotAllowedInForInStatement(#[label] pub Span);
#[error("Using declarations must have an initializer.")] #[error("Using declarations must have an initializer.")]
#[diagnostic()] #[diagnostic()]
pub struct UsingDeclarationsMustBeInitialized(#[label] pub Span); pub struct UsingDeclarationsMustBeInitialized(#[label] pub Span);
#[derive(Debug, Error, Diagnostic)]
#[error("TS1089: `static` modifier cannot appear on a constructor declaration.")]
#[diagnostic()]
pub struct StaticConstructor(#[label] pub Span);

View file

@ -1,7 +1,7 @@
use oxc_allocator::{Box, Vec}; use oxc_allocator::{Box, Vec};
use oxc_ast::{ast::*, syntax_directed_operations::PropName}; use oxc_ast::{ast::*, syntax_directed_operations::PropName};
use oxc_diagnostics::Result; use oxc_diagnostics::Result;
use oxc_span::Span; use oxc_span::{GetSpan, Span};
use super::list::ClassElements; use super::list::ClassElements;
use crate::{diagnostics, lexer::Kind, list::NormalList, Parser, StatementContext}; use crate::{diagnostics, lexer::Kind, list::NormalList, Parser, StatementContext};
@ -365,6 +365,17 @@ impl<'a> Parser<'a> {
self.error(diagnostics::SetterParameters(value.params.span)); self.error(diagnostics::SetterParameters(value.params.span));
} }
if kind == MethodDefinitionKind::Constructor {
if let Some(this_param) = &value.this_param {
// class Foo { constructor(this: number) {} }
self.error(diagnostics::TSConstructorThisParameter(this_param.span));
}
if r#static {
self.error(diagnostics::StaticConstructor(key.span()));
}
}
let method_definition = MethodDefinition { let method_definition = MethodDefinition {
span: self.end_span(span), span: self.end_span(span),
key, key,

View file

@ -68,15 +68,6 @@ impl<'a> Parser<'a> {
pub(crate) fn parse_formal_parameters( pub(crate) fn parse_formal_parameters(
&mut self, &mut self,
params_kind: FormalParameterKind, params_kind: FormalParameterKind,
) -> Result<Box<'a, FormalParameters<'a>>> {
let span = self.start_span();
let list = FormalParameterList::parse(self)?;
Ok(self.ast.formal_parameters(self.end_span(span), params_kind, list.elements, list.rest))
}
pub(crate) fn parse_formal_parameters_with_ts_this(
&mut self,
params_kind: FormalParameterKind,
) -> Result<(Option<TSThisParameter<'a>>, Box<'a, FormalParameters<'a>>)> { ) -> Result<(Option<TSThisParameter<'a>>, Box<'a, FormalParameters<'a>>)> {
let span = self.start_span(); let span = self.start_span();
let list: FormalParameterList<'_> = FormalParameterList::parse(self)?; let list: FormalParameterList<'_> = FormalParameterList::parse(self)?;
@ -101,7 +92,7 @@ impl<'a> Parser<'a> {
let type_parameters = self.parse_ts_type_parameters()?; let type_parameters = self.parse_ts_type_parameters()?;
let (this_param, params) = let (this_param, params) =
self.parse_formal_parameters_with_ts_this(FormalParameterKind::FormalParameter)?; self.parse_formal_parameters(FormalParameterKind::FormalParameter)?;
let return_type = self.parse_ts_return_type_annotation()?; let return_type = self.parse_ts_return_type_annotation()?;
@ -476,7 +467,13 @@ impl<'a> Parser<'a> {
let type_parameters = self.parse_ts_type_parameters()?; let type_parameters = self.parse_ts_type_parameters()?;
let params = self.parse_formal_parameters(FormalParameterKind::ArrowFormalParameters)?; let (this_param, params) =
self.parse_formal_parameters(FormalParameterKind::ArrowFormalParameters)?;
if let Some(this_param) = this_param {
// const x = (this: number) => {};
self.error(diagnostics::TSArrowFunctionThisParameter(this_param.span));
}
let return_type = self.parse_ts_return_type_annotation()?; let return_type = self.parse_ts_return_type_annotation()?;

View file

@ -784,7 +784,13 @@ impl<'a> Parser<'a> {
let r#abstract = self.eat(Kind::Abstract); let r#abstract = self.eat(Kind::Abstract);
self.expect(Kind::New)?; self.expect(Kind::New)?;
let type_parameters = self.parse_ts_type_parameters()?; let type_parameters = self.parse_ts_type_parameters()?;
let params = self.parse_formal_parameters(FormalParameterKind::Signature)?; let (this_param, params) = self.parse_formal_parameters(FormalParameterKind::Signature)?;
if let Some(this_param) = this_param {
// type Foo = new (this: number) => any;
self.error(diagnostics::TSConstructorThisParameter(this_param.span));
}
self.expect(Kind::Arrow)?; self.expect(Kind::Arrow)?;
let return_type_span = self.start_span(); let return_type_span = self.start_span();
let return_type = self.parse_ts_return_type()?; let return_type = self.parse_ts_return_type()?;
@ -802,8 +808,7 @@ impl<'a> Parser<'a> {
fn parse_ts_function_type(&mut self) -> Result<TSType<'a>> { fn parse_ts_function_type(&mut self) -> Result<TSType<'a>> {
let span = self.start_span(); let span = self.start_span();
let type_parameters = self.parse_ts_type_parameters()?; let type_parameters = self.parse_ts_type_parameters()?;
let (this_param, params) = let (this_param, params) = self.parse_formal_parameters(FormalParameterKind::Signature)?;
self.parse_formal_parameters_with_ts_this(FormalParameterKind::Signature)?;
self.expect(Kind::Arrow)?; self.expect(Kind::Arrow)?;
let return_type_span = self.start_span(); let return_type_span = self.start_span();
let return_type = self.parse_ts_return_type()?; let return_type = self.parse_ts_return_type()?;
@ -920,8 +925,7 @@ impl<'a> Parser<'a> {
pub(crate) fn parse_ts_call_signature_member(&mut self) -> Result<TSSignature<'a>> { pub(crate) fn parse_ts_call_signature_member(&mut self) -> Result<TSSignature<'a>> {
let span = self.start_span(); let span = self.start_span();
let type_parameters = self.parse_ts_type_parameters()?; let type_parameters = self.parse_ts_type_parameters()?;
let (this_patam, params) = let (this_patam, params) = self.parse_formal_parameters(FormalParameterKind::Signature)?;
self.parse_formal_parameters_with_ts_this(FormalParameterKind::Signature)?;
let return_type = self.parse_ts_return_type_annotation()?; let return_type = self.parse_ts_return_type_annotation()?;
self.bump(Kind::Comma); self.bump(Kind::Comma);
self.bump(Kind::Semicolon); self.bump(Kind::Semicolon);
@ -938,8 +942,7 @@ impl<'a> Parser<'a> {
let span = self.start_span(); let span = self.start_span();
self.expect(Kind::Get)?; self.expect(Kind::Get)?;
let (key, computed) = self.parse_property_name()?; let (key, computed) = self.parse_property_name()?;
let (this_param, params) = let (this_param, params) = self.parse_formal_parameters(FormalParameterKind::Signature)?;
self.parse_formal_parameters_with_ts_this(FormalParameterKind::Signature)?;
let return_type = self.parse_ts_return_type_annotation()?; let return_type = self.parse_ts_return_type_annotation()?;
self.bump(Kind::Comma); self.bump(Kind::Comma);
self.bump(Kind::Semicolon); self.bump(Kind::Semicolon);
@ -960,8 +963,7 @@ impl<'a> Parser<'a> {
let span = self.start_span(); let span = self.start_span();
self.expect(Kind::Set)?; self.expect(Kind::Set)?;
let (key, computed) = self.parse_property_name()?; let (key, computed) = self.parse_property_name()?;
let (this_param, params) = let (this_param, params) = self.parse_formal_parameters(FormalParameterKind::Signature)?;
self.parse_formal_parameters_with_ts_this(FormalParameterKind::Signature)?;
let return_type = self.parse_ts_return_type_annotation()?; let return_type = self.parse_ts_return_type_annotation()?;
self.bump(Kind::Comma); self.bump(Kind::Comma);
self.bump(Kind::Semicolon); self.bump(Kind::Semicolon);
@ -1034,7 +1036,13 @@ impl<'a> Parser<'a> {
self.expect(Kind::New)?; self.expect(Kind::New)?;
let type_parameters = self.parse_ts_type_parameters()?; let type_parameters = self.parse_ts_type_parameters()?;
let params = self.parse_formal_parameters(FormalParameterKind::Signature)?; let (this_param, params) = self.parse_formal_parameters(FormalParameterKind::Signature)?;
if let Some(this_param) = this_param {
// interface Foo { new(this: number): Foo }
self.error(diagnostics::TSConstructorThisParameter(this_param.span));
}
let return_type = self.parse_ts_return_type_annotation()?; let return_type = self.parse_ts_return_type_annotation()?;
self.bump(Kind::Comma); self.bump(Kind::Comma);
self.bump(Kind::Semicolon); self.bump(Kind::Semicolon);

View file

@ -19592,6 +19592,30 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ let o8 = { ...*o }; 3 │ let o8 = { ...*o };
╰──── ╰────
× TS2681: A constructor cannot have a `this` parameter.
╭─[conformance/types/thisType/thisTypeInFunctionsNegative.ts:159:1]
159 │ class ThisConstructor {
160 │ constructor(this: ThisConstructor, private n: number) {
· ─────────────────────
161 │ }
╰────
× TS2681: A constructor cannot have a `this` parameter.
╭─[conformance/types/thisType/thisTypeInFunctionsNegative.ts:163:1]
163 │ interface ThisConstructorInterface {
164 │ new(this: ThisConstructor, n: number);
· ─────────────────────
165 │ }
╰────
× TS2681: A constructor cannot have a `this` parameter.
╭─[conformance/types/thisType/thisTypeInFunctionsNegative.ts:165:1]
165 │ }
166 │ var thisConstructorType: new (this: number) => number;
· ────────────
167 │ function notFirst(a: number, this: C): number { return this.n; }
╰────
× Expected `,` but found `this` × Expected `,` but found `this`
╭─[conformance/types/thisType/thisTypeInFunctionsNegative.ts:169:1] ╭─[conformance/types/thisType/thisTypeInFunctionsNegative.ts:169:1]
169 │ ///// parse errors ///// 169 │ ///// parse errors /////