You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Lyuben Atanasov (Jira)" <ji...@apache.org> on 2023/11/13 16:08:00 UTC
[jira] [Created] (GROOVY-11222) Cannot parse methods that return types starting with lowercase letters
Lyuben Atanasov created GROOVY-11222:
----------------------------------------
Summary: Cannot parse methods that return types starting with lowercase letters
Key: GROOVY-11222
URL: https://issues.apache.org/jira/browse/GROOVY-11222
Project: Groovy
Issue Type: Bug
Components: parser
Affects Versions: 4.0.15, 5.0.0-alpha-2
Reporter: Lyuben Atanasov
According to the language specification, it is allowed to have class names that start with a lowercase letter:
{quote}Identifiers start with a letter, a dollar or an underscore. They cannot start with a number.
A letter can be in the following ranges:
* 'a' to 'z' (lowercase ascii letter)
* 'A' to 'Z' (uppercase ascii letter)
* '\u00C0' to '\u00D6'
* '\u00D8' to '\u00F6'
* '\u00F8' to '\u00FF'
* '\u0100' to '\uFFFE'{quote}
This is the same as in Java.
Defining types that start with lowercase letters works fine. As far as I can tell, I can also use such types as method arguments. What I cannot do, is to have methods that return types starting with lowercase letters.
Here's a failing example:
{code:groovy}
public class person {
private String firstName;
private String lastName;
person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
public class PersonFactory {
public person createPerson(String firstName, String lastName) {
return new person(firstName, lastName);
}
}
{code}
When parsing this code, it fails with the following error:
{noformat}
Script_b41cda4fe6804e170255542089871d79.groovy: 13: Unexpected input: '(' @ line 13, column 31.
public person createPerson(String firstName, String lastName) {
^
1 error
{noformat}
If I change the class name to start with a capital letter, everything works:
{code:groovy}
public class Person {
private String firstName;
private String lastName;
Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
public class PersonFactory {
public Person createPerson(String firstName, String lastName) {
return new Person(firstName, lastName);
}
}
{code}
So it looks like there is a discrepancy between the language specification and the grammar definition. I looked into the grammar and managed to extract the following relevant lines from it, which should make the issue evident:
{code:java}
methodDeclaration[int t, int ct]
: modifiersOpt typeParameters? (returnType[$ct] nls)?
methodName formalParameters
(
DEFAULT nls elementValue
|
(nls THROWS nls qualifiedClassNameList)?
(nls methodBody)?
)?
;
returnType[int ct]
:
standardType
| VOID
;
standardType
options { baseContext = type; }
: annotationsOpt
(
primitiveType
|
standardClassOrInterfaceType
)
emptyDimsOpt
;
standardClassOrInterfaceType
options { baseContext = classOrInterfaceType; }
: qualifiedStandardClassName typeArguments?
;
qualifiedStandardClassName
: qualifiedNameElements className (DOT className)*
;
className
: CapitalizedIdentifier
;
{code}
Here, it is allowed only to have a CapitalizedIdentifier as the class name. There is an obvious simple fix:
{code:java}
className
: CapitalizedIdentifier | Identifier
;
{code}
This should make the parser work in the same way as expected after reading the language spec. I am not sure, however, whether this won't break anything else.
In order to avoid any unnecessary discussions about naming conventions: I am aware that by convention it is not OK to start a type name with anything other than a capital letter, but there are valid cases where it is desired to have such names (e.g. generated code based on external input, DSLs).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)