mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(linter): check PrivateIdentifier in javascript
This commit is contained in:
parent
44675e8cd8
commit
ed161cc38e
7 changed files with 2348 additions and 243 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -922,6 +922,7 @@ dependencies = [
|
|||
name = "oxc_linter"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"indextree",
|
||||
"insta",
|
||||
"lazy_static",
|
||||
"miette",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ oxc_semantic = { path = "../oxc_semantic" }
|
|||
|
||||
lazy_static = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
indextree = { workspace = true }
|
||||
|
||||
[dev_dependencies]
|
||||
oxc_allocator = { path = "../oxc_allocator" }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use indextree::{Ancestors, NodeId};
|
||||
use oxc_ast::AstKind;
|
||||
use oxc_diagnostics::Error;
|
||||
use oxc_semantic::{AstNodes, Scope, ScopeTree, Semantic};
|
||||
use oxc_semantic::{AstNodes, Scope, ScopeTree, Semantic, SemanticNode};
|
||||
|
||||
use crate::{
|
||||
fixer::{Fix, Message},
|
||||
|
|
@ -63,6 +64,11 @@ impl<'a> LintContext<'a> {
|
|||
self.semantic().nodes()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn kind(&self, node_id: NodeId) -> AstKind<'a> {
|
||||
self.nodes().kind(node_id)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn parent_kind(&self, node: &AstNode<'a>) -> AstKind<'a> {
|
||||
self.nodes().parent_kind(node)
|
||||
|
|
@ -73,6 +79,12 @@ impl<'a> LintContext<'a> {
|
|||
node.parent().and_then(|node_id| self.nodes().get(node_id))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn ancestors(&self, node: &AstNode<'a>) -> Ancestors<'_, SemanticNode<'a>> {
|
||||
let node_id = self.nodes().get_node_id(node).unwrap();
|
||||
node_id.ancestors(self.nodes())
|
||||
}
|
||||
|
||||
/* Scopes */
|
||||
|
||||
#[must_use]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#[allow(clippy::wildcard_imports)]
|
||||
use oxc_ast::{ast::*, AstKind, Span};
|
||||
use oxc_ast::{ast::*, AstKind, Atom, Span};
|
||||
use oxc_diagnostics::{
|
||||
miette::{self, Diagnostic},
|
||||
thiserror::Error,
|
||||
|
|
@ -14,6 +14,7 @@ impl Rule for EarlyErrorJavaScript {
|
|||
#[allow(clippy::single_match)]
|
||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
match node.get().kind() {
|
||||
AstKind::PrivateIdentifier(ident) => check_private_identifier(ident, node, ctx),
|
||||
AstKind::RegExpLiteral(lit) => check_regexp_literal(lit, ctx),
|
||||
AstKind::NumberLiteral(lit) => check_number_literal(lit, node, ctx),
|
||||
_ => {}
|
||||
|
|
@ -21,6 +22,68 @@ impl Rule for EarlyErrorJavaScript {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_private_identifier<'a>(
|
||||
ident: &PrivateIdentifier,
|
||||
node: &AstNode<'a>,
|
||||
ctx: &LintContext<'a>,
|
||||
) {
|
||||
// Ignore private identifier declaration inside class
|
||||
if matches!(ctx.parent_kind(node), AstKind::PropertyKey(_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find enclosing classes
|
||||
let mut classes = vec![];
|
||||
for node_id in ctx.ancestors(node).skip(1) {
|
||||
let kind = ctx.kind(node_id);
|
||||
if let AstKind::Class(class) = kind {
|
||||
classes.push(class);
|
||||
}
|
||||
// stop lookup when the class is a heritage, e.g.
|
||||
// `class C extends class extends class { x = this.#foo; } {} { #foo }`
|
||||
// `class C extends function() { x = this.#foo; } { #foo }`
|
||||
if matches!(kind, AstKind::ClassHeritage(_)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if classes.is_empty() {
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("Private identifier '#{0:?}' is not allowed outside class bodies")]
|
||||
#[diagnostic()]
|
||||
struct PrivateNotInClass(Atom, #[label] Span);
|
||||
ctx.diagnostic(PrivateNotInClass(ident.name.clone(), ident.span));
|
||||
return;
|
||||
};
|
||||
|
||||
// Check private identifier declarations in class.
|
||||
// This implementations does a simple lookup for private identifier declarations inside a class.
|
||||
// Performance can be improved by storing private identifiers for each class inside a lookup table,
|
||||
// but there are not many private identifiers in the wild so we should be good fow now.
|
||||
let found_private_ident = classes.iter().any(|class| {
|
||||
class.body.body.iter().any(|def| {
|
||||
// let key = match def {
|
||||
// ClassElement::PropertyDefinition(def) => &def.key,
|
||||
// ClassElement::MethodDefinition(def) => &def.key,
|
||||
// _ => return false,
|
||||
// };
|
||||
if let Some(key) = def.property_key()
|
||||
&& let PropertyKey::PrivateIdentifier(prop_ident) = key {
|
||||
return prop_ident.name == ident.name;
|
||||
}
|
||||
false
|
||||
})
|
||||
});
|
||||
|
||||
if !found_private_ident {
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("Private field '{0:?}' must be declared in an enclosing class")]
|
||||
#[diagnostic()]
|
||||
struct PrivateFieldUndeclared(Atom, #[label] Span);
|
||||
ctx.diagnostic(PrivateFieldUndeclared(ident.name.clone(), ident.span));
|
||||
}
|
||||
}
|
||||
|
||||
fn check_number_literal(lit: &NumberLiteral, node: &AstNode, ctx: &LintContext) {
|
||||
// NumericLiteral :: LegacyOctalIntegerLiteral
|
||||
// DecimalIntegerLiteral :: NonOctalDecimalIntegerLiteral
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ mod scope;
|
|||
use std::rc::Rc;
|
||||
|
||||
pub use builder::SemanticBuilder;
|
||||
pub use node::{AstNode, AstNodes};
|
||||
pub use node::{AstNode, AstNodes, SemanticNode};
|
||||
use oxc_ast::Trivias;
|
||||
pub use scope::{Scope, ScopeTree};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
TypeScript Summary:
|
||||
AST Parsed : 4329/4869 (88.91%)
|
||||
Positive Passed: 4329/4869 (88.91%)
|
||||
AST Parsed : 4306/4869 (88.44%)
|
||||
Positive Passed: 4306/4869 (88.44%)
|
||||
Expect to Parse: "async/es2017/asyncArrowFunction/asyncArrowFunction6_es2017.ts"
|
||||
|
||||
× Automatic Semicolon Insertion
|
||||
|
|
@ -343,6 +343,23 @@ Expect to Parse: "classes/classDeclarations/classWithPredefinedTypesAsNames2.ts"
|
|||
· ──┬─
|
||||
· ╰── Expect `{` here, but found `void`
|
||||
╰────
|
||||
Expect to Parse: "classes/classStaticBlock/classStaticBlock16.ts"
|
||||
|
||||
× Private field '"y"' must be declared in an enclosing class
|
||||
╭─[classes/classStaticBlock/classStaticBlock16.ts:12:1]
|
||||
12 │ getX = (obj: C) => obj.#x;
|
||||
13 │ getY = (obj: D) => obj.#y;
|
||||
· ──
|
||||
14 │ }
|
||||
╰────
|
||||
|
||||
× Private field '"x"' must be declared in an enclosing class
|
||||
╭─[classes/classStaticBlock/classStaticBlock16.ts:22:1]
|
||||
22 │ // getY has privileged access to y
|
||||
23 │ getX = (obj: C) => obj.#x;
|
||||
· ──
|
||||
24 │ getY = (obj: D) => obj.#y;
|
||||
╰────
|
||||
Expect to Parse: "classes/classStaticBlock/classStaticBlock20.ts"
|
||||
|
||||
× Expect token
|
||||
|
|
@ -412,6 +429,74 @@ Expect to Parse: "classes/members/accessibility/privateInstanceMemberAccessibili
|
|||
13 │ }
|
||||
╰────
|
||||
help: Try insert a semicolon here
|
||||
Expect to Parse: "classes/members/privateNames/privateNameAccessorsAccess.ts"
|
||||
|
||||
× Private identifier '#"prop"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameAccessorsAccess.ts:15:1]
|
||||
15 │ }
|
||||
16 │ new A2().#prop; // Error
|
||||
· ─────
|
||||
17 │
|
||||
╰────
|
||||
|
||||
× Private identifier '#"prop"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameAccessorsAccess.ts:18:1]
|
||||
18 │ function foo (){
|
||||
19 │ new A2().#prop; // Error
|
||||
· ─────
|
||||
20 │ }
|
||||
╰────
|
||||
|
||||
× Private field '"prop"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameAccessorsAccess.ts:23:1]
|
||||
23 │ m() {
|
||||
24 │ new A2().#prop;
|
||||
· ─────
|
||||
25 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameAccessorssDerivedClasses.ts"
|
||||
|
||||
× Private field '"prop"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameAccessorssDerivedClasses.ts:10:1]
|
||||
10 │ static method(x: Derived) {
|
||||
11 │ console.log(x.#prop);
|
||||
· ─────
|
||||
12 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameAndAny.ts"
|
||||
|
||||
× Private field '"bar"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameAndAny.ts:11:1]
|
||||
11 │ thing.#baz;
|
||||
12 │ thing.#bar; // Error
|
||||
· ────
|
||||
13 │ thing.#foo();
|
||||
╰────
|
||||
|
||||
× Private field '"bar"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameAndAny.ts:18:1]
|
||||
18 │ thing.#baz;
|
||||
19 │ thing.#bar;
|
||||
· ────
|
||||
20 │ thing.#foo();
|
||||
╰────
|
||||
|
||||
× Private field '"bar"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameAndAny.ts:25:1]
|
||||
25 │ thing.#baz;
|
||||
26 │ thing.#bar;
|
||||
· ────
|
||||
27 │ thing.#foo();
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameAndIndexSignature.ts"
|
||||
|
||||
× Private field '"f"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameAndIndexSignature.ts:8:1]
|
||||
8 │ constructor(message: string) {
|
||||
9 │ this.#f = 3 // Error (index signatures do not implicitly declare private names)
|
||||
· ──
|
||||
10 │ this["#foo"] = 3; // Okay (type has index signature and "#foo" does not collide with private identifier #foo)
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameAndPropertySignature.ts"
|
||||
|
||||
× Unexpected token
|
||||
|
|
@ -421,6 +506,39 @@ Expect to Parse: "classes/members/privateNames/privateNameAndPropertySignature.t
|
|||
· ────
|
||||
3 │ #bar(): string;
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameBadAssignment.ts"
|
||||
|
||||
× Private identifier '#"nope"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameBadAssignment.ts:2:1]
|
||||
2 │
|
||||
3 │ exports.#nope = 1; // Error (outside class body)
|
||||
· ─────
|
||||
4 │ function A() { }
|
||||
╰────
|
||||
|
||||
× Private identifier '#"no"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameBadAssignment.ts:4:1]
|
||||
4 │ function A() { }
|
||||
5 │ A.prototype.#no = 2; // Error (outside class body)
|
||||
· ───
|
||||
6 │
|
||||
╰────
|
||||
|
||||
× Private identifier '#"foo"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameBadAssignment.ts:7:1]
|
||||
7 │ class B {}
|
||||
8 │ B.#foo = 3; // Error (outside class body)
|
||||
· ────
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Private field '"foo"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameBadAssignment.ts:13:1]
|
||||
13 │ exports.#bar = 6; // Error
|
||||
14 │ this.#foo = 3; // Error (undeclared)
|
||||
· ────
|
||||
15 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameBadDeclaration.ts"
|
||||
|
||||
× Unexpected token
|
||||
|
|
@ -1170,6 +1288,15 @@ Expect to Parse: "classes/members/privateNames/privateNameEnum.ts"
|
|||
· ──
|
||||
4 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameFieldDerivedClasses.ts"
|
||||
|
||||
× Private field '"prop"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameFieldDerivedClasses.ts:10:1]
|
||||
10 │ static method(x: Derived) {
|
||||
11 │ console.log(x.#prop);
|
||||
· ─────
|
||||
12 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameHashCharName.ts"
|
||||
|
||||
× Invalid Character `'\r'`
|
||||
|
|
@ -1180,6 +1307,15 @@ Expect to Parse: "classes/members/privateNames/privateNameHashCharName.ts"
|
|||
· ╰── Invalid Character `
`
|
||||
4 │
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameImplicitDeclaration.ts"
|
||||
|
||||
× Private field '"x"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameImplicitDeclaration.ts:8:1]
|
||||
8 │ /** @type {string} */
|
||||
9 │ this.#x;
|
||||
· ──
|
||||
10 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameInInExpression.ts"
|
||||
|
||||
× Expect token
|
||||
|
|
@ -1227,6 +1363,39 @@ Expect to Parse: "classes/members/privateNames/privateNameInObjectLiteral-3.ts"
|
|||
· ────
|
||||
3 │ return ""
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameJsBadAssignment.ts"
|
||||
|
||||
× Private identifier '#"nope"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameJsBadAssignment.ts:6:1]
|
||||
6 │
|
||||
7 │ exports.#nope = 1; // Error (outside class body)
|
||||
· ─────
|
||||
8 │ function A() { }
|
||||
╰────
|
||||
|
||||
× Private identifier '#"no"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameJsBadAssignment.ts:8:1]
|
||||
8 │ function A() { }
|
||||
9 │ A.prototype.#no = 2; // Error (outside class body)
|
||||
· ───
|
||||
10 │
|
||||
╰────
|
||||
|
||||
× Private identifier '#"foo"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameJsBadAssignment.ts:11:1]
|
||||
11 │ class B {}
|
||||
12 │ B.#foo = 3; // Error (outside class body)
|
||||
· ────
|
||||
13 │
|
||||
╰────
|
||||
|
||||
× Private field '"foo"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameJsBadAssignment.ts:16:1]
|
||||
16 │ constructor () {
|
||||
17 │ this.#foo = 3; // Error (undeclared)
|
||||
· ────
|
||||
18 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameJsBadDeclaration.ts"
|
||||
|
||||
× Unexpected token
|
||||
|
|
@ -1236,6 +1405,74 @@ Expect to Parse: "classes/members/privateNames/privateNameJsBadDeclaration.ts"
|
|||
· ──
|
||||
9 │ #m() {}, // Error
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameMethodAccess.ts"
|
||||
|
||||
× Private identifier '#"method"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameMethodAccess.ts:13:1]
|
||||
13 │ }
|
||||
14 │ new A2().#method(); // Error
|
||||
· ───────
|
||||
15 │
|
||||
╰────
|
||||
|
||||
× Private identifier '#"method"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameMethodAccess.ts:16:1]
|
||||
16 │ function foo (){
|
||||
17 │ new A2().#method(); // Error
|
||||
· ───────
|
||||
18 │ }
|
||||
╰────
|
||||
|
||||
× Private field '"method"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameMethodAccess.ts:21:1]
|
||||
21 │ m() {
|
||||
22 │ new A2().#method();
|
||||
· ───────
|
||||
23 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameMethodClassExpression.ts"
|
||||
|
||||
× Private identifier '#"method"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameMethodClassExpression.ts:10:1]
|
||||
10 │ console.log(C.getInstance().getField());
|
||||
11 │ C.getInstance().#method; // Error
|
||||
· ───────
|
||||
12 │ C.getInstance().#field; // Error
|
||||
╰────
|
||||
|
||||
× Private identifier '#"field"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameMethodClassExpression.ts:11:1]
|
||||
11 │ C.getInstance().#method; // Error
|
||||
12 │ C.getInstance().#field; // Error
|
||||
· ──────
|
||||
13 │
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameMethodsDerivedClasses.ts"
|
||||
|
||||
× Private field '"prop"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameMethodsDerivedClasses.ts:10:1]
|
||||
10 │ static method(x: Derived) {
|
||||
11 │ console.log(x.#prop());
|
||||
· ─────
|
||||
12 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameNestedMethodAccess.ts"
|
||||
|
||||
× Private field '"unknown"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameNestedMethodAccess.ts:20:1]
|
||||
20 │ x.#bar;
|
||||
21 │ x.#unknown; // Error
|
||||
· ────────
|
||||
22 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts"
|
||||
|
||||
× Private identifier '#"foo"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameNotAccessibleOutsideDefiningClass.ts:7:1]
|
||||
7 │
|
||||
8 │ new A().#foo = 4; // Error
|
||||
· ────
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameNotAllowedOutsideClass.ts"
|
||||
|
||||
× Unexpected token
|
||||
|
|
@ -1244,6 +1481,57 @@ Expect to Parse: "classes/members/privateNames/privateNameNotAllowedOutsideClass
|
|||
4 │ const #foo = 3;
|
||||
· ────
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameStaticAccessorsAccess.ts"
|
||||
|
||||
× Private identifier '#"prop"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameStaticAccessorsAccess.ts:16:1]
|
||||
16 │
|
||||
17 │ A2.#prop; // Error
|
||||
· ─────
|
||||
18 │
|
||||
╰────
|
||||
|
||||
× Private identifier '#"prop"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameStaticAccessorsAccess.ts:19:1]
|
||||
19 │ function foo (){
|
||||
20 │ A2.#prop; // Error
|
||||
· ─────
|
||||
21 │ }
|
||||
╰────
|
||||
|
||||
× Private field '"prop"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameStaticAccessorsAccess.ts:24:1]
|
||||
24 │ m() {
|
||||
25 │ A2.#prop;
|
||||
· ─────
|
||||
26 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameStaticAccessorssDerivedClasses.ts"
|
||||
|
||||
× Private field '"prop"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameStaticAccessorssDerivedClasses.ts:10:1]
|
||||
10 │ static method(x: typeof Derived) {
|
||||
11 │ console.log(x.#prop);
|
||||
· ─────
|
||||
12 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameStaticFieldDerivedClasses.ts"
|
||||
|
||||
× Private field '"derivedProp"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameStaticFieldDerivedClasses.ts:5:1]
|
||||
5 │ static method(x: Derived) {
|
||||
6 │ Derived.#derivedProp // error
|
||||
· ────────────
|
||||
7 │ Base.#prop = 10;
|
||||
╰────
|
||||
|
||||
× Private field '"prop"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameStaticFieldDerivedClasses.ts:13:1]
|
||||
13 │ Derived.#derivedProp
|
||||
14 │ Base.#prop = 10; // error
|
||||
· ─────
|
||||
15 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameStaticMethodAsync.ts"
|
||||
|
||||
× Expect token
|
||||
|
|
@ -1254,6 +1542,41 @@ Expect to Parse: "classes/members/privateNames/privateNameStaticMethodAsync.ts"
|
|||
· ╰── Expect `(` here, but found `*`
|
||||
14 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameStaticMethodClassExpression.ts"
|
||||
|
||||
× Private identifier '#"method"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameStaticMethodClassExpression.ts:10:1]
|
||||
10 │ console.log(C.getClass().getField());
|
||||
11 │ C.getClass().#method; // Error
|
||||
· ───────
|
||||
12 │ C.getClass().#field; // Error
|
||||
╰────
|
||||
|
||||
× Private identifier '#"field"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNameStaticMethodClassExpression.ts:11:1]
|
||||
11 │ C.getClass().#method; // Error
|
||||
12 │ C.getClass().#field; // Error
|
||||
· ──────
|
||||
13 │
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNameUncheckedJsOptionalChain.ts"
|
||||
|
||||
× Private field '"foo"' must be declared in an enclosing class
|
||||
╭─[classes/members/privateNames/privateNameUncheckedJsOptionalChain.ts:9:1]
|
||||
9 │ constructor () {
|
||||
10 │ this?.#foo;
|
||||
· ────
|
||||
11 │ this?.#bar;
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNamesAndGenericClasses-2.ts"
|
||||
|
||||
× Private identifier '#"foo"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNamesAndGenericClasses-2.ts:26:1]
|
||||
26 │ const x: number = a.baz // OK
|
||||
27 │ a.#foo; // Error
|
||||
· ────
|
||||
28 │ a = b; // Error
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNamesAndIndexedAccess.ts"
|
||||
|
||||
× Unexpected token
|
||||
|
|
@ -1263,6 +1586,31 @@ Expect to Parse: "classes/members/privateNames/privateNamesAndIndexedAccess.ts"
|
|||
· ────
|
||||
12 │ // will never use this syntax, already taken:
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNamesInGenericClasses.ts"
|
||||
|
||||
× Private identifier '#"foo"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNamesInGenericClasses.ts:25:1]
|
||||
25 │ declare let b: C<string>;
|
||||
26 │ a.#foo; // Error
|
||||
· ────
|
||||
27 │ a.#method; // Error
|
||||
╰────
|
||||
|
||||
× Private identifier '#"method"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNamesInGenericClasses.ts:26:1]
|
||||
26 │ a.#foo; // Error
|
||||
27 │ a.#method; // Error
|
||||
· ───────
|
||||
28 │ a.#prop; // Error
|
||||
╰────
|
||||
|
||||
× Private identifier '#"prop"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNamesInGenericClasses.ts:27:1]
|
||||
27 │ a.#method; // Error
|
||||
28 │ a.#prop; // Error
|
||||
· ─────
|
||||
29 │ a = b; // Error
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNamesIncompatibleModifiers.ts"
|
||||
|
||||
× Expect token
|
||||
|
|
@ -1273,6 +1621,15 @@ Expect to Parse: "classes/members/privateNames/privateNamesIncompatibleModifiers
|
|||
· ╰── Expect `(` here, but found `#identifier`
|
||||
31 │ async set #asyncProp(value: number) { } // Error
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNamesInterfaceExtendingClass.ts"
|
||||
|
||||
× Private identifier '#"prop"' is not allowed outside class bodies
|
||||
╭─[classes/members/privateNames/privateNamesInterfaceExtendingClass.ts:11:1]
|
||||
11 │ function func(x: I) {
|
||||
12 │ x.#prop = 123;
|
||||
· ─────
|
||||
13 │ }
|
||||
╰────
|
||||
Expect to Parse: "classes/members/privateNames/privateNamesNotAllowedAsParameters.ts"
|
||||
|
||||
× Unexpected token
|
||||
|
|
@ -5828,6 +6185,14 @@ Expect to Parse: "salsa/plainJSGrammarErrors.ts"
|
|||
· ╰── Expect `in` here, but found `Identifier`
|
||||
10 │ #p
|
||||
╰────
|
||||
Expect to Parse: "salsa/privateIdentifierExpando.ts"
|
||||
|
||||
× Private identifier '#"bar"' is not allowed outside class bodies
|
||||
╭─[salsa/privateIdentifierExpando.ts:7:1]
|
||||
7 │ const x = {};
|
||||
8 │ x.#bar.baz = 20;
|
||||
· ────
|
||||
╰────
|
||||
Expect to Parse: "scanner/ecmascript3/scannerES3NumericLiteral3.ts"
|
||||
|
||||
× Automatic Semicolon Insertion
|
||||
|
|
|
|||
Loading…
Reference in a new issue