Changed behavior in object field access in Groovy 3.0? - groovy

I've recently stumbled on this issue when assisting in the migration of some legacy code.
The following used to execute correctly in Groovy 2.4.x :
class Person {
String name
}
def me = new Person( name : 'Joe' )
assert me.(name) == 'Joe'
while it raises an exception when executed on Groovy 3.0.2 :
groovy.lang.MissingPropertyException: No such property: name for class: MyScript
Enclosing the property name in parentheses actually looks wrong to me: as a matter of fact, I was surprised that an exception was not raised in older releases too.
The syntax I would probably have used is either:
assert me.name == 'Joe'
or something like:
assert me.'name' == 'Joe'
which work in both versions 2.4 AND 3.0.
I did some research and couldn't find anything in the Changelogs from Groovy 2.4 through Groovy 3.0 that refers to something that could affect this behavior.
Am I missing something here?
Was the fact that the code worked in 2.4 an unexpected behavior, which has been corrected?
Or is this actually expected to work?
My guess is that it has to do with the switch to the new Parrot parser in version 3.0.
Thanks!

When you wrap the property name in parens, like "me.(name)", you are using dynamic property syntax. Groovy is supposed to resolve "name" in the enclosing scope and not against the receiver. If you want to get the "name" property from "me", you can write "me.name" or "me.'name'" or "me['name']" or "me.getProperty('name')".

Related

Groovy Pattern for matching a value in map

Hy guys, i'm working on a IDEA plugin and custom references. I have many references working, but i'm stuck with a difficult one.
I'd like to detect patterns in groovy such as this one :
result = run service: 'createAgreementItem', with: createAgreementItemInMap
In the above line, i'd like to get the createAgreementItem element to match.
run is defined in a groovy base script
package org.apache.ofbiz.service.engine
abstract class GroovyBaseScript extends Script {
//...
Map run(Map args) throws ExecutionServiceException {
return runService((String)args.get('service'), (Map)args.get('with', new HashMap()))
}
//...
The problem is, what i'm trying to get isn't technically a parameter, it's a value from a map with the key equals to service.
So this won't work :
GroovyPatterns.groovyLiteralExpression()
.methodCallParameter(0,
GroovyPatterns.psiMethod().withName("run")
.definedInClass("org.apache.ofbiz.service.engine.GroovyBaseScript"))
Do you have any ideas or any help ? Thanks in advance !
EDIT :
Actually, i'm looking for a doc or an example for any use of the org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns
library.
I don't get it, maybe i'm not familiar enough with groovy though i used it a bit.
Any help welcome on this.
The problem is, what i'm trying to get isn't technically a parameter,
it's a value from a map with the key equals to "service"
If all you want to do is retrieve the service value from the Map then instead of args.get('with', new HashMap()) you could do args.with.service. If you wanted null safety, you could do args?.with?.service.

Groovy version downgrade 2.2.1

We have been building our application using groovy 2.3.6. Now because of some platform level issues we are advised to downgrade our groovy version to 2.2.1. I am facing no. of issues regarding this downgrade.
groovy is not able to infer the type of it variable in ver 2.2.1 so if i have code something like this
names.any { sliceName.endsWith(it) }
it gives me exception
[Static type checking] - Cannot find matching method java.lang.String#endsWith(java.lang.Object)
Secondly all the default method that i had used in collections no longer seem to exist
positions.any { it.primary }
groovy is unable to find the any method on list.
One way would be turn off static type checking, which will expose the code to a lot more runtime errors.
Is there any way to resolve these errors, without turning off static type checking. Also are these features only added in groovy 2.3.6 like default groovy methods and type inference for it variable
If you go back to an old version, old bugs will bite you.
Try giving the static compiler more of a hint
names.any { String it -> sliceName.endsWith(it) }

Catel ServiceLocatorRegistration attribute get compile error message

I try to create automatically registering with Catel framework,
[ServiceLocatorRegistration(typeof(ISalesOrderListViewModel))]
public class SalesOrderListViewModel : ISalesOrderListViewModel
{
}
But i got this error when compile this code.
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
Does Catel ServiceLocatorRegistration attribute need something I don't know?
help!!
Finally I find under net framework 4.5, this attribute works fine, but when I try to run this under net framework 4.0, this attribute doesn't work, which meaning I get compile error.
Mr. Geert, I don't know I should submit this to issue track or you may don't support this under net framework 4.0.

Nullreference exception in Update.Setwrap after updating Mongo Driver

I am in Mongo-C# environment and we have been coding against Mongo for a while using Mongo 1.3.x DLL. Recently, I updated it to be 1.4.2 and everything else was fine until I faced a problem where I noticed that while previous version of Mongo DLL was treating
update.SetWrapped(property.Name, value);
all file when value was null but the recent version does not like it and it throws nullreference exception.
Problem here is that I would like it to be able to accept Null values. has anybody faced this problem before? If yes, how did you handle that?
There was a breaking change when this was introduced. You need to use BsonNull.Value for this. So, your code would look like this:
update.SetWrapped(property.Name, BsonValue.Create(value) ?? BsonNull.Value);
I believe you should have been able to pass C# null to Update.SetWrapped<T> because T is a POCO and not a BsonValue and the serializer for T would decide how to serialize C# null.
I've created a JIRA ticket for this:
https://jira.mongodb.org/browse/CSHARP-486
Note that while C# driver versions earlier than 1.4 did not throw a NullReferenceException, they also did not update the property to BSON null as you might have expected (passing C# null to SetWrapped turned the SetWrapped into a no-op in earlier versions).
The basic rules for C# null handling are clear:
C# null is not a valid BsonValue, use BsonNull.Value instead
C# null is valid for POCOs, and will probably be serialized as a BSON null (although technically a serializer for a POCO could choose a different representation)

Using constructor to load data in subsonic3?

I'm getting an error while trying to load an record through the constructor.
The constructor is:
public Document(Expression<Func<Document,bool>> expression);
and i try to load a single item in like this
var x = new Document(f=>f.publicationnumber=="xxx");
publicationnumber isn't a key but tried making an it an unique key and still no go..
Am i totally wrong regarding the use of the constructor? and can someone please tell me how to use that constructor?
The error i'm getting is:
Test method TestProject1.UnitTest1.ParseFileNameTwoProductSingleLanguage threw exception: System.NullReferenceException:
with the following stacktrace:
SubSonic.Query.SqlQuery.Where[T](Expression1` expression)
Load`[T]`(T item, Expression1expression)
db.Document..ctor(Expression``1 expression) in C:\#Projects\DocumentsSearchAndAdmin\DocumentsSearchAndAdmin\Generated\ActiveRecord.cs: line 5613
rest removed for simplicity
Regards
Dennis
Use == instead of =, i.e.:
...(f=>f.publicationnumber == "xxx");
I've just gotten the SubSonic source, and found out that it had to with the expression parser and my lack of knowledge thereof .. my right side of the expression was actually an item in an string array - and s[PUBNO] (PUBNO is a const) and it was looking for an column named s instead of publicationnumber, i don't know if this i a bug or not in the linq classes
none the less - i've managed to get it to work by creating a local variable containing the value of s[PUBNO] and using that instead...
//dennis

Resources