[ https://issues.apache.org/jira/browse/GROOVY-11222?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17786018#comment-17786018 ]
Paul King edited comment on GROOVY-11222 at 11/15/23 6:01 AM: -------------------------------------------------------------- We decided to make a breaking change in Groovy 4 here. Thus this is no bug and expected. The GLS only talks about identifiers, not class names. I guess it needs an update here. the reason for this change is that there are problems with the name resolution leading to very long compilation times in which the compiler basically looks for non-existing classes. This is because for example "def foo = String" is valid in Groovy. It is not the only example causing problems, just the most easy to understand. Using 3rd party libraries or generated code in groovy, that is not following the conventions can be worked around. Groovy supports import aliases. Thus you can do "import com.generated.something.foo as Foo" and if you then do "def foo = Foo" it will resolve to the class com.generated.something.foo. This alias can be used anywhere, also in implements or extends. was (Author: blackdrag): We decided to make a breaking change in Groovy 4 here. Thus this is no bug and expected. The GSL only talks about identifiers, not class names. I guess it needs an update here. the reason for this change is that there are problems with the name resolution leading to very long compilation times in which the compiler basically looks for non-existing classes. This is because for example "def foo = String" is valid in Groovy. It is not the only example causing problems, just the most easy to understand. Using 3rd party libraries or generated code in groovy, that is not following the conventions can be worked around. Groovy supports import aliases. Thus you can do "import com.generated.something.foo as Foo" and if you then do "def foo = Foo" it will resolve to the class com.generated.something.foo. This alias can be used anywhere, also in implements or extends. > 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: 5.0.0-alpha-2, 4.0.15 > Reporter: Lyuben Atanasov > Assignee: Jochen Theodorou > Priority: Major > > 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)