How to fix the error "Calling Function without definition !: init" in the Ring programming language? - scripting-language

Why the next program produce the runtime error message "Error (R3) : Calling Function without definition !: init"
load "guilib.ring"
new qApp() {
new qWidget() {
setWindowTitle("First App!")
resize(400,400)
show()
}
exec()
}

The next code will fix your problem
Load "guilib.ring"
New qApp {
New qWidget() {
setWindowTitle("First App!")
resize(400,400)
show()
}
exec()
}
Using () after the class name means calling the init() method in the class and passing parameters to this method, using () while no init() method in the class will generate a runtime error message.
the class qApp don’t have this method while the other classes have it because they need it to create an object using a function that return a pointer to that object and this pointer will be stored in an attribute called pObject, for more information see ring_qt.ring file which contains the classes.

Related

How can I make a WireBox injected dependency available to a constructor method?

In this example, I have a model object called test.cfc which has a dependency testService.cfc.
test has WireBox inject testService through a property declaration. The object looks like this:
component {
property name="testService" inject="testService";
/**
* Constructor
*/
function init() {
// do something in the test service
testService.doSomething();
return this;
}
}
For reference, testService has a single method called doSomething() which dumps out some text:
component
singleton
{
/**
* Constructor
*/
function init() {
return this;
}
/**
* Do Something
*/
function doSomething() {
writeDump( "something" );
}
}
The problem is, WireBox doesn't seem to inject testService until after the constructor init() method fires. So, if I run this in my handler:
prc.test = wirebox.getInstance(
name = "test"
);
I get the following error message: Error building: test -> Variable TESTSERVICE is undefined.. DSL: , Path: models.test
Just for sanity sake, if I modify test so that testService gets referenced after the object is constructed, everything works fine. The problem seems to be isolated to constructor methods.
How can I make sure my dependencies can be referenced in my object constructor methods? Thanks for your assistance!
Due to the order of construction, you can't use property or setter injections in the init() method. Instead, you can access them in the onDIComplete() method. I realized the WireBox docs only had a passing reference to this, so I have added this excerpt:
https://wirebox.ortusbooks.com/usage/injection-dsl/id-model-empty-namespace#cfc-instantiation-order
CFC Building happens in this order.
Component is instantiated with createObject()
CF automatically runs the pseudo constructor (any code outside the a method declaration)
The init() method is called (if it exists), passing any constructor args
Property (mixin) and setting injection happens
The onDIComplete() method is called (if it exists)
So the proper version of your CFC would be as follows:
component {
property name="testService" inject="testService";
/**
* Constructor
*/
function init() {
return this;
}
/**
* Called after property and setter injections are processed
*/
function onDIComplete() {
// do something in the test service
testService.doSomething();
}
}
Note, it would also be acceptable to switch to constructor injection, but my personal preference is property injection due to the reduced boilerplate of needing to receive the argument and persist it locally.
https://wirebox.ortusbooks.com/usage/wirebox-injector/injection-idioms

Mocking findFiles in JenkinsPipelineUnit

Currently I'm trying to register findFiles step.
My set up is as follows:
src/
test/
groovy/
TestJavaLib.groovy
vars/
javaLib.groovy
javaApp.jenkinsfile
Inside TestJavaApp.groovy I have:
...
import com.lesfurets.jenkins.unit.RegressionTest
import com.lesfurets.jenkins.unit.BasePipelineTest
class TestJavaLibraryPipeline extends BasePipelineTest implements RegressionTest {
// Some overridden setUp() which loads shared libs
// and registers methods referenced in javaLib.groovy
void registerPipelineMethods() {
...
def fileList = [new File("testFile1"), new File("testFile2")]
helper.registerAllowedMethod('findFiles', { f -> return fileList })
...
}
}
and my javaLib.groovy contains this currently failing part:
...
def pomFiles = findFiles glob: "target/publish/**/${JOB_BASE_NAME}*.pom"
if (pomFiles.length < 1) { // Fails with java.lang.NullPointerException: Cannot get property 'length' on null object
error("no pom file found")
}
...
I have tried multiple closures returning various objects, but everytime I get NPE.
Question is - how to correctly register "findFiles" method?
N.B. That I'm very new to mocking and closures in groovy.
Looking at the source code and examples on GitHub, I see a few overloads of the method (here):
void registerAllowedMethod(String name, List<Class> args = [], Closure closure)
void registerAllowedMethod(MethodSignature methodSignature, Closure closure)
void registerAllowedMethod(MethodSignature methodSignature, Function callback)
void registerAllowedMethod(MethodSignature methodSignature, Consumer callback)
It doesn't look like you are registering the right signature with your call. I'm actually surprised you aren't getting a MissingMethodException with your current call pattern.
You need to add the rest of the method signature during registration. The findFiles method is taking a Map of parameters (glob: "target/publish/**/${JOB_BASE_NAME}*.pom" is a map literal in Groovy). One way to register that type would be like this:
helper.registerAllowedMethod('findFiles', [Map.class], { f -> return fileList })
I also faced the same issue. However, I was able to mock the findFiles() method using the following method signature:
helper.registerAllowedMethod(method('findFiles', Map.class), {map ->
return [['path':'testPath/test.zip']]
})
So I found a way on how to mock findFiles when I needed length property:
helper.registerAllowedMethod('findFiles', [Map.class], { [length: findFilesLength ?: 1] })
This also allows to change findFilesLength variable in tests to test different conditions in pipeline like the one in my OP.

Overloading a method in Groovy using Closure arguments with different return types

I'm reasonably proficient with Groovy insofar as my job requires, but not having a background in OOP means that some things still elude me, so apologies if some of the wording is a little off here (feel free to edit if you can make the question clearer).
I'm trying to create an overloaded method where the signature (ideally) differs only in the return type of the single Closure parameter. The Closure contains a method call that returns either an ItemResponse or ListResponse object, both of which could contain an object/objects of any type (which is the type I would like to infer).
The following code is a simplified version of what I'm trying to implement - an error handling method which takes a reference to a service call, safely attempts to resolve it, and returns the item/items from the response as appropriate:
public <T> T testMethod(Closure<ItemResponse<T>> testCall) {
testCall.call().item as T
}
public <T> List<T> testMethod(Closure<ListResponse<T>> testCall) {
testCall.call().items as T
}
Obviously this doesn't work, but is there any alternate approach/workaround that would achieve the desired outcome?
I'm trying to create an overloaded method where the signature
(ideally) differs only in the return type of the single Closure
parameter.
You cannot do that because the return type is not part of the method signature. For example, the following is not valid:
class Demo {
int doit() {}
String doit() {}
}
As mentioned by yourself and #jeffscottbrown, you can't have two methods with the same parameters but different return value. The workaround I can see here is to use a call-back closure. The return value of your testMethod would default to Object and you would provide an "unwrapper" that would the bit after the closure call (extract item or items). Try this out in your GroovyConsole:
class ValueHolder <T> {
T value
}
Closure<List<Integer>> c = {
[1]
}
Closure<ValueHolder<String>> d = {
new ValueHolder(value:'hello world')
}
Closure liu = {List l ->
l.first()
}
Closure vhsu = {ValueHolder vh ->
vh.value
}
// this is the generic method
public <T> Object testMethod(Closure<T> testCall, Closure<T> unwrapper) {
unwrapper(testCall.call()) as T
}
println testMethod(c, liu)
println testMethod(d, vhsu)
It works with both a list or a value holder.

How can I invoke a field which has a function assigned in Class level

How can I invoke a field which has a function assigned in Class level?
This is the code snippet i am using:
class Foo {
let alias = whatever
func whatever() -> Int {
return 3
}
}
print(Foo().alias) // print out this is a function
print(Foo().alias()) // compilation error about missing argument
First of all, I know I can use Foo.whatever() instead.
but let me explain why I ask this question.
So normally if I am using playground, it is working as I expect if I have a function and then I assign it to a variable. It has exact same code but it is just out of class scope.
let alias = whatever
func whatever() -> Int {
return 3
}
print(alias) // print out function
print(alias()) // print 3 so it is working as expected
Dont know why I cant invoke it in the Class level, if it is impossible to invoke it, why swift doesnt have compilation error about let alias = whatever in class level
You can not invoke it in the Class level because alias is not an instance method, but a function which returns another function (whatever in this case). And Swift compiler does provide Missing argument for parameter #1 in call compilation error, as you've mentioned in your first code block:
print(Foo().alias()) // compilation error about missing argument
You may invoke whatever function via alias like this:
let instance = Foo()
instance.alias(instance)()
It means that alias function has a single argument, a Foo instance, and returns another function. This latter function takes nothing and returns Int, that is type of alias is:
(Foo) -> () -> Int
Basically, an instance method in Swift is simply a type method that takes the instance as an argument and returns a function which will then be applied to the instance:
Foo.whatever(instance)()
Check the actual alias type with the following code:
println(Foo().alias.dynamicType)
To do that you need a computed property, this will work:
class Foo {
var alias : () -> Int { get{ return whatever}}
func whatever() -> Int {
return 3
}
}
print(Foo().alias) // print out this is a function
print(Foo().alias()) // 3

How to create an object from a function

I am trying to create a wrapper for lunr.js (http://lunrjs.com/) in Dart, however, I can find no documentation on how to use this with the Dart js interop.
This is the object I am trying to create:
var index = lunr(function () {
this.field('title', {boost: 10})
this.field('body')
this.ref('id')
})
Currently this is all that I have.
JsObject index = new JsObject(context['lunr'], [()
{
}]);
How am I able to access this from an anonymous function?
Also where do I put the actual lunr.js? I am simply making a wrapper for it so I don't see any reason to have it in a HTML file unless necessary.
EDIT:
I have also tried:
Create a function to allow for using this keyword. (still not sure if this syntax is correct)
_f = new JsFunction.withThis( (t) {
t.callMethod('field', ['title', {boost: 10}])
t.callMethod('field', ['body'])
t.callMethod('ref', ['id'])
});
Then create a JsObject using that function:
JsObject index = new JsObject(context['lunr'], [_f]);
This will give me this error:
Exception: Unhandled exception:
Closure call with mismatched arguments: function 'call'
NoSuchMethodError: incorrect number of arguments passed to method named 'call'
Receiver: Closure: (dynamic) => dynamic
Tried calling: call(Instance of 'JsObject', Instance of 'JsObject')
Found: call(t)
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:45)
Next I tried this:
JsObject index =new JsObject.fromBrowserObject(context['lunr']);
That gives me a different error: Exception: Illegal argument(s): object cannot be a num, string, bool, or null
This may be because I do not have a way to call the _f function when creating the JsObject that way.
You have to use :
context.callMethod('lunr', [_f]);
new JsObject(context['lunr'], [_f]); is the same as new lunr(f) in JS.
I think if you just use it in the function it will be closurized with the function. Otherwise you can try using an emulated function where you pass the this when you instantiate an instance of the emulated function.
class SomeFunction implements Function {
ThisType thisVal;
SomeFunction(this.thisVal);
call(args) {
thisVal.field(...);
}
}
I don't know dart at all, but perhaps you can sidestep the issue of trying to use this entirely. The function you pass to the lunr function has the created index yielded as the first param as well as being the context of the function.
var index = lunr(function (idx) {
idx.field('title', { boost: 10 })
idx.field('body')
idx.ref('id')
})
The above uses the yielded index object rather than relying on the context being set as the index, so you don't need to use this.

Resources