Skip to content

Commit f7cf55b

Browse files
authored
fix: report a missing class name as a syntax error
A class declaration with no name did not produce a SyntaxError: class {} no message resource found for message id: parser.error.expected.ident class 1 {} same className() asked for the message key parser.error.expected.ident, which does not exist. ECMAErrors.getMessage turns the MissingResourceException into a plain RuntimeException, so the error was neither a ParserException nor - under JSR-223 - a ScriptException. There is no need for a new key: this is the same "Expected X but found Y" that expectDontAdvance reports everywhere else, so className() now builds it the same way, through the existing "expected" key. That also fixes the argument, which named the token being looked at rather than the one that was wrong: the message said "class" where the offending token was "{". class {} Expected ident but found { class 1 {} Expected ident but found 1 Two error tests come with it. Neither a malformed class name nor a duplicated constructor had one, which is why a message key that never resolved could ship. The duplicate-constructor message was already correct and is now covered. ./gradlew build testOptimistic testPessimistic: suite before after test 665, 0 fail 665, 0 fail testOptimistic 1715, 0 fail 1717, 0 fail testPessimistic 1715, 0 fail 1717, 0 fail
1 parent 100129d commit f7cf55b

5 files changed

Lines changed: 75 additions & 1 deletion

File tree

src/main/java/org/codelibs/sai/internal/parser/Parser.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,9 @@ private IdentNode className() {
11191119
final int nameIndex = k + 1;
11201120

11211121
if (T(nameIndex) != IDENT) {
1122-
throw error(AbstractParser.message("expected.ident", type.getNameOrType()), getToken(nameIndex));
1122+
final long nameToken = getToken(nameIndex);
1123+
throw error(AbstractParser.message("expected", IDENT.getNameOrType(), Token.toString(source, nameToken)),
1124+
nameToken);
11231125
}
11241126

11251127
return createIdentNode(getToken(nameIndex), finish, (String) getValue(getToken(nameIndex)));
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2026, CodeLibs Project and/or its affiliates. All rights reserved.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*/
18+
19+
/**
20+
* A class body may define at most one constructor.
21+
*
22+
* @test/compile-error
23+
* @option --language=es6
24+
*/
25+
26+
class Point {
27+
constructor() {
28+
}
29+
30+
constructor() {
31+
}
32+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
test/script/error/class_duplicate_constructor.js:30:4 A class may only have one constructor
2+
constructor() {
3+
^
4+
test/script/error/class_duplicate_constructor.js:31:4 Expected eof but found }
5+
}
6+
^
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2026, CodeLibs Project and/or its affiliates. All rights reserved.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*/
18+
19+
/**
20+
* A class declaration needs a name. Saying so has to be an ordinary syntax error
21+
* rather than a missing message resource.
22+
*
23+
* @test/compile-error
24+
* @option --language=es6
25+
*/
26+
27+
class {
28+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
test/script/error/class_name_missing.js:27:6 Expected ident but found {
2+
class {
3+
^
4+
test/script/error/class_name_missing.js:28:0 Expected eof but found }
5+
}
6+
^

0 commit comments

Comments
 (0)