How to use local scope variables in Groovy Script Engine? - variables

All variables seem to be global in my groovy scripts I run on groovy script engine. I made some groovy class but when I make variables, they can be accessed from everywhere. for exaple.
class test{
void func1{ a=4 }
void func2{ print(a) }
}
When I invoke this class function func1 from scala then invoke func2, it results "4". Weird thing is if I declare variables like "def a=0" in the function, the scope of the variable will be limited with in the function.
I'm loading my groovy scripts from GroovyScriptEngine like this(using scala)
var gse = new GroovyScriptEngine(pathList.toArray)
var scriptClass = gse.loadScriptByName(file.getName())
var i = scriptClass.newInstance().asInstanceOf[GroovyObject]
then using invokeMethod to invoke functions in the groove script class. Is there anyway to make variable scopes limited with in functions by default?

That's the expected behaviour, described in Scoping and the Semantics of "def".
Using an undeclared variable in a Groovy script creates a binding variable. Binding variables are global to your script. If you declare your variable with def, it become function local.
This behavior only applies because you load your code as a script. I don't believe its possible to change it. Just use a declaration (def or a type) when you need a local variable.
Note that you can also define a binding variable (global) by using the #Field annotation:
class test {
void func1{ #Field int a=4 }
void func2{ print(a) }
}
is equivalent to
class test {
void func1{ a=4 }
void func2{ print(a) }
}

Related

Is there a way to hide the INSTANCE variable on a Kotlin singleton object

If I have code like this
object ObjectTest {
#JvmStatic
fun init() {
}
}
is it possible to hide the ObjectTest.INSTANCE variable that Kotlin automatically generates? I don't want the object to be accessible via an instance and nor will it have any instance methods, so the INSTANCE variable is just polluting autocomplete and could be confusing to potential users (This code is for a library that will be consumed by others).
Yes, you can do it, by converting an object into a plain file.
#file:JvmName("ObjectTest")
// maybe a package statement here
fun init() {
// here `init` is public static final void
}
And there's no INSTANCE object. In Kotlin this is a top-level function, but in Java it's a class named ObjectTest with a private constructor and it has a public static final void method called init.

Create Method via GDSL script that has a delegating closure parameter

Using the (scarcely documented) gdsl scripts of Intellij, one can add dynamic methods to a class:
contributor(context(ctype: "my.Type")) {
method name: "doIt", params: [body: {}], type: void
}
One can also configure the delegation of a closure:
contributor(context(scope: closureScope())) {
def call = enclosingCall("doIt")
if (call) {
def method = call.bind()
def clazz = method?.containingClass
if (clazz?.qualName == 'my.Type') {
delegatesTo(findClass('my.Inner'))
}
}
}
Which, when doIt is a method that is defined in the code (not dynamically added), also works as designed.
However, when using the closureScope with the previously created method, the containing class method is always null, meaning that I can not safely delegate inside the closure to the addressed my.Inner class.
What I want is adding a dynamic method equivalent to:
void doIt(#DelegatesTo(my.Inner) Closure)...
I.e. I want the method to be available in code completion (this works), and inside the so created closure, I want correct code completion when addressing methods of my.Inner.
So far, I tried various approaches:
include the #DelegatesTo annotation in the param definition
try more esoteric approaches in finding the owner of the closure, which fails because the GrMethodCall simply has no parent
unconditionally delegating all closures named doIt to my.Inner which works, but is no viable solution since I do have multiple doIt methods (on different classes) delegating to different targets.
So, how can I make IDEA behave as expected and delegate to the correct target?
Edit to make it clearer:
Given the following classes:
package my
class Type {
void doIt(Closure) {}
}
class Inner {
void inInner() {}
}
and the following gdsl:
contributor(context(scope: closureScope())) {
def call = enclosingCall("doIt")
if (call) {
def method = call.bind()
def clazz = method?.containingClass
println clazz?.qualName
if (clazz?.qualName == 'my.Type') {
delegatesTo(findClass('my.Inner'))
}
}
}
when I start typing in a new script:
new Type().doIt {
inInner()
}
When inside the closure, I get the following:
code completion for inInner
inInner is shown as valid
The console output when started with idea.bat from commandline shows the line my.Type (from the println)
Ctrl-B on inInner correctly links to source code.
(The same behaviour can be reached without the gdsl when annotation the Closure Parameter in the doIt method with #DelegatesTo(Inner))
However, I do not want to manually include the doIt method in the source of Type, it is generated by an AST Transformation, so my source file now looks like this:
package my
class Type {
}
class Inner {
void inInner() {}
}
I can tell IntelliJ about the new method using the following gdsl snippet
contributor(context(ctype: "my.Type")) {
method name: "doIt", params: [body: {}], type: void
}
Now the IDE correctly recognizes the doIt method with a closure parameter. However, inside the Closure, the following happens:
sometimes code completion shows inInner, sometimes after changing something, it does not (when using the original code to fix a type, it was shown, but later declared "unresolved", after going through the code changes of this edited example, it is not shown anymore...)
Even when shown, inInner is shown with "cannot resolve symbol" decoration
the console shows null as clazz, i.e. the method is found, but not linked to an owner ASTNode
Ctrl-B does not link to the corresponding method in Inner
So what I want is the same behaviour for an injected doIt method (via Gdsl) as with a method included in the source, i.e. I want the gdsl to inject a doIt method with a delegating closure (to Inner) into the type class.
This worked for me adding the ctype to scope insted of finding the class type from the method
contributor(context(scope: closureScope(), ctype: 'my.Type')) {
def call = enclosingCall("doIt")
if (call) {
delegatesTo(findClass('my.Inner'))
}
}

Specifying method's behaviour via EXPECT_CALL vs in body

From what I understand gmock (and I'm new to it) EXPECT_CALL allows for specifying how a method will behave when it's called (in this case I'm mostly interested in what it will return). But I could just as well define the method explicitly with its body. Example:
class Factory
{
int createSomething();
};
class MockFactory : public Factory
{
MOCK_METHOD0(createSomething, int());
};
int main()
{
...
int something(5);
MockFactory mockFactory;
EXPECT_CALL(mockFactory, createSomething()).WillRepeatedly(Return(something));
...
}
vs
class MockFactory : public Factory
{
int createSomething()
{
return 5;
}
};
Now, if createSomething were to behave differently (return different things) in different scenarios then obviously I should use EXPECT_CALL. But if it's going to always return the same thing wouldn't it be better to just explicitly define the method's body? (Note that other methods in the mocked class might still use EXPECT_CALL.)
When you define a method you miss all the flexibility that mocking that method can give you in the tests.
If you need to assert in a test that createSomething gets called, you can only do it if you have mocked it, not if you have a standard method definition. Not in this case, but in case of methods taking parameters, it's even better to have a mock.
If you need to set up a default action that your method should perform, even when you don't set any expectations on it, do so using ON_CALL macro in the SetUp member function of a TestFixture.

invoke a method using Javassist

I'm a newbie to Javassist and trying few tutorials. I understand that Javassist helps to manipulate bytecode and helps achieving structural reflection. As mentioned in wiki (http://en.wikipedia.org/wiki/Javassist), I believe it does have support to achieve reflection.
I'm trying to do a basic evaluation to understand howmuch time would java reflection takes to invoke a method and howmuch time would javassist takes. In the process, assume I have a class:
public class Addition {
public int add(int a, int b){
return a+b;
}
}
Now, using java reflection api, I would use the following code to calculate howmuch time will be taken to invoke 100 objects:
import java.lang.reflect.*;
public class ReflectionClass {
/**
* #param args
*/
public static void main(String[] args) {
int numberOfObjects = 10000;
double start,time;
try {
Class cls = Class.forName("Addition");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod(
"add", partypes);
Addition methobj = new Addition();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
start = System.currentTimeMillis();
for(int i=0;i<numberOfObjects;i++){
Object retobj= meth.invoke(methobj, arglist);
Integer retval = (Integer)retobj;
System.out.println(retval.intValue());
}
time = System.currentTimeMillis() - start;
System.out.println("Method call for "+numberOfObjects +" objects is::"+time +" milliseconds");
}
catch (Throwable e) {
System.err.println(e);
}
}
}
Now, I'm not sure how to proceed with javassist. i.e.,
I will create a ctclass object and store the class I'm going to read. and I could also get all the declaredmethods using getdeclaredmethods and store it in a ctMethod variable.
But, unlike java reflection api, I can't find an invoke method in ctMethod api of javassist. Does this mean, I've to create a duplicate method and have to make a call to the original method as explained in: http://www.ibm.com/developerworks/java/library/j-dyn0916/index.html.
I'm not sure if this is the right way to proceed.
Am I missing something?
Javassist is used to change existing classes or generate new ones programmatically. Its reflective capabilities are used during the transformation of existing classes to find out details about the class being transformed.
The reflective capabilities of javassist are similar to those of the reflection api, but javassist has no way to invoke methods (unless you generate code that invokes those methods of course).
What you could do, is use javassist to transform the main method of your ReflectionClass such that the timing code is added dynamically, i.e. you could build a primitive profiler with it. Then you could leave the timing code out of the source file of ReflectionClass and add it at run-time when the class is loaded into the JVM.
Another approach would be to generate a class that 'invokes 100 objects' as you say, but timing it wouldn't be very interesting because it would run just as fast as regular java bytecode.

Can method parameters be dynamic in C#

In c# 4.0, are dynamic method parameters possible, like in the following code?
public string MakeItQuack(dynamic duck)
{
string quack = duck.Quack();
return quack;
}
I've many cool examples of the dynamic keyword in C# 4.0, but not like above. This question is of course inspired by how python works.
Yes, you can absolutely do that. For the purposes of static overload resolution, it's treated as an object parameter (and called statically). What you do within the method will then be dynamic. For example:
using System;
class Program
{
static void Foo(dynamic duck)
{
duck.Quack(); // Called dynamically
}
static void Foo(Guid ignored)
{
}
static void Main()
{
// Calls Foo(dynamic) statically
Foo("hello");
}
}
The "dynamic is like object" nature means you can't have one overload with just an object parameter and one with just a dynamic parameter.
See documentation http://msdn.microsoft.com/en-us/library/dd264741(VS.100).aspx
Yes, you can do that. As stated in C# 4.0 specification, the grammar is extended to support dynamic wherever a type is expected:
type:
...
dynamic
This includes parameter definitions, of course.
Yes; see e.g.
http://blogs.msdn.com/cburrows/archive/2008/11/14/c-dynamic-part-vi.aspx
or Chris' other blogs. Or grab VS2010 Beta2 and try it out.