adjust message to accommodate more cases

pull/15820/head
Rich Harris 4 months ago
parent 63e60c76a3
commit c82ede5cf6

@ -6,6 +6,7 @@
"request": "launch", "request": "launch",
"name": "Run sandbox", "name": "Run sandbox",
"program": "${workspaceFolder}/playgrounds/sandbox/run.js", "program": "${workspaceFolder}/playgrounds/sandbox/run.js",
"runtimeExecutable": "node",
"env": { "env": {
"NODE_OPTIONS": "--stack-trace-limit=10000" "NODE_OPTIONS": "--stack-trace-limit=10000"
} }

@ -208,37 +208,6 @@ Cannot assign to %thing%
Cannot bind to %thing% Cannot bind to %thing%
``` ```
### constructor_state_reassignment
```
A state field declaration in a constructor must be the first assignment, and the only one that uses a rune
```
[State fields]($state#Classes) can be declared as normal class fields or inside the constructor, in which case the declaration must be the _first_ assignment.
Assignments thereafter must not use the rune.
```ts
constructor() {
this.count = $state(0);
this.count = $state(1); // invalid, assigning to the same property with `$state` again
}
constructor() {
this.count = $state(0);
this.count = $state.raw(1); // invalid, assigning to the same property with a different rune
}
constructor() {
this.count = 0;
this.count = $state(1); // invalid, this property was created as a regular property, not state
}
constructor() {
this.count = $state(0);
this.count = 1; // valid, this is setting the state that has already been declared
}
```
### css_empty_declaration ### css_empty_declaration
``` ```
@ -877,6 +846,32 @@ Cannot reassign or bind to snippet parameter
This snippet is shadowing the prop `%prop%` with the same name This snippet is shadowing the prop `%prop%` with the same name
``` ```
### state_field_duplicate
```
`%name%` has already been declared on this class
```
An assignment to a class field that uses a `$state` or `$derived` rune is considered a _state field declaration_. The declaration can happen in the class body...
```js
class Counter {
count = $state(0);
}
```
...or inside the constructor...
```js
class Counter {
constructor() {
this.count = $state(0);
}
}
```
...but it can only happen once.
### state_invalid_export ### state_invalid_export
``` ```

@ -10,35 +10,6 @@
> Cannot bind to %thing% > Cannot bind to %thing%
## constructor_state_reassignment
> A state field declaration in a constructor must be the first assignment, and the only one that uses a rune
[State fields]($state#Classes) can be declared as normal class fields or inside the constructor, in which case the declaration must be the _first_ assignment.
Assignments thereafter must not use the rune.
```ts
constructor() {
this.count = $state(0);
this.count = $state(1); // invalid, assigning to the same property with `$state` again
}
constructor() {
this.count = $state(0);
this.count = $state.raw(1); // invalid, assigning to the same property with a different rune
}
constructor() {
this.count = 0;
this.count = $state(1); // invalid, this property was created as a regular property, not state
}
constructor() {
this.count = $state(0);
this.count = 1; // valid, this is setting the state that has already been declared
}
```
## declaration_duplicate ## declaration_duplicate
> `%name%` has already been declared > `%name%` has already been declared
@ -241,6 +212,30 @@ It's possible to export a snippet from a `<script module>` block, but only if it
> Cannot reassign or bind to snippet parameter > Cannot reassign or bind to snippet parameter
## state_field_duplicate
> `%name%` has already been declared on this class
An assignment to a class field that uses a `$state` or `$derived` rune is considered a _state field declaration_. The declaration can happen in the class body...
```js
class Counter {
count = $state(0);
}
```
...or inside the constructor...
```js
class Counter {
constructor() {
this.count = $state(0);
}
}
```
...but it can only happen once.
## state_invalid_export ## state_invalid_export
> Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties > Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties

@ -105,12 +105,13 @@ export function constant_binding(node, thing) {
} }
/** /**
* A state field declaration in a constructor must be the first assignment, and the only one that uses a rune * `%name%` has already been declared on this class
* @param {null | number | NodeLike} node * @param {null | number | NodeLike} node
* @param {string} name
* @returns {never} * @returns {never}
*/ */
export function constructor_state_reassignment(node) { export function state_field_duplicate(node, name) {
e(node, 'constructor_state_reassignment', `A state field declaration in a constructor must be the first assignment, and the only one that uses a rune\nhttps://svelte.dev/e/constructor_state_reassignment`); e(node, 'state_field_duplicate', `\`${name}\` has already been declared on this class\nhttps://svelte.dev/e/state_field_duplicate`);
} }
/** /**

@ -54,7 +54,7 @@ export function ClassBody(node, context) {
if (rune && is_state_creation_rune(rune)) { if (rune && is_state_creation_rune(rune)) {
if (seen.includes(name)) { if (seen.includes(name)) {
e.constructor_state_reassignment(node); // TODO the same thing applies to duplicate fields, so the code/message needs to change e.state_field_duplicate(node, name);
} }
state_fields[name] = { state_fields[name] = {

@ -1,7 +1,7 @@
[ [
{ {
"code": "constructor_state_reassignment", "code": "state_field_duplicate",
"message": "A state field declaration in a constructor must be the first assignment, and the only one that uses a rune", "message": "`count` has already been declared on this class",
"start": { "start": {
"line": 5, "line": 5,
"column": 2 "column": 2

@ -1,7 +1,7 @@
[ [
{ {
"code": "constructor_state_reassignment", "code": "state_field_duplicate",
"message": "A state field declaration in a constructor must be the first assignment, and the only one that uses a rune", "message": "`count` has already been declared on this class",
"start": { "start": {
"line": 5, "line": 5,
"column": 2 "column": 2

@ -1,7 +1,7 @@
[ [
{ {
"code": "constructor_state_reassignment", "code": "state_field_duplicate",
"message": "A state field declaration in a constructor must be the first assignment, and the only one that uses a rune", "message": "`count` has already been declared on this class",
"start": { "start": {
"line": 5, "line": 5,
"column": 2 "column": 2

@ -1,7 +1,7 @@
[ [
{ {
"code": "constructor_state_reassignment", "code": "state_field_duplicate",
"message": "A state field declaration in a constructor must be the first assignment, and the only one that uses a rune", "message": "`count` has already been declared on this class",
"start": { "start": {
"line": 5, "line": 5,
"column": 2 "column": 2

@ -1,7 +1,7 @@
[ [
{ {
"code": "constructor_state_reassignment", "code": "state_field_duplicate",
"message": "A state field declaration in a constructor must be the first assignment, and the only one that uses a rune", "message": "`count` has already been declared on this class",
"start": { "start": {
"line": 4, "line": 4,
"column": 2 "column": 2

@ -1,7 +1,7 @@
[ [
{ {
"code": "constructor_state_reassignment", "code": "state_field_duplicate",
"message": "A state field declaration in a constructor must be the first assignment, and the only one that uses a rune", "message": "`count` has already been declared on this class",
"start": { "start": {
"line": 4, "line": 4,
"column": 2 "column": 2

@ -1,7 +1,7 @@
[ [
{ {
"code": "constructor_state_reassignment", "code": "state_field_duplicate",
"message": "A state field declaration in a constructor must be the first assignment, and the only one that uses a rune", "message": "`count` has already been declared on this class",
"start": { "start": {
"line": 7, "line": 7,
"column": 2 "column": 2

Loading…
Cancel
Save