How to Retrieve Method's Signature in Squeak - reflection

printThisMethodSig: aSomething
stack := thisContext stackOfSize: 2.
Transcript show: (stack at: 2); cr.
stack at: 2 returns the method context of the current method. It is possible to retrieve the compiled method of the current method using method message. I want to be able to print the whole signature of the method, for example: from:to:.
I looked at both MethodContext and CompiledMethod classes but could not find out how to do it.
Thank you.

You can use the selector message to retrieve the name of a CompiledMethod.

Related

Firebase-Authentication error in objects 'mAuth' and 'mCallbacks'

the mAuth and mCallbacks object is giving red-font-error. How to resolve this?
Do I need to make the object outside of the codeblock?
here is the code block in which the red-font errors are showing up:
PhoneAuthOptions options =
PhoneAuthOptions.newBuilder(mAuth)
.setPhoneNumber(phoneNumber) // Phone number to verify
.setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
.setActivity(this) // Activity (for callback binding)
.setCallbacks(mCallbacks) // OnVerificationStateChangedCallbacks
.build();
PhoneAuthProvider.verifyPhoneNumber(options);
If you keep following the documentation on implementing phone authentication on Android, you'll see that the mCallbacks object is defined in the next step, right under the code you have above. It is explained as:
When you call PhoneAuthProvider.verifyPhoneNumber, you must also provide an instance ofOnVerificationStateChangedCallbacks, which contains implementations of the callback functions that handle the results of the request.
Under that explanation is a code sample, and then an explanation of each individual callback and its purpose.
I recommend reading the entire page first, so that you understand the complete flow, and only then starting to copy/paste the relevant code snippets.

Kotlin Bundle.putString not explicitly adding "String" but instead is "String?"

val args = Bundle()
args.putString("type", details.type)
navigator.navigate(context!!, findNavController(), Destination.TYPE, args)
I am quite confused as to why in the receiving fragment when I go to access the arguments I have passed through it is responding with...
val type: String = arguments.getString("type")
The arguments.getString is all underlined red and says "Required String Found String?" But how when I called method "putString"?!?
It is resulting in text not being rendered in the new fragment and I assume this is a nullability issue.
It's a matter of knowledge that is available in the receiving Fragment.
The Fragment is not aware of how its arguments were created (or modified) so it has to assume the "type" key you're looking for might not be in the arguments Bundle. That's why it returns a nullable (String?) result (the null value would mean absent in arguments).
Your fragment might be created in many places in your app and its arguments might have been modified in many places. We have no way of tracking that.
There are different solutions for this problem, depending on your approach in other parts of the code and how "confident" you are in creating of your Fragment.
I would usually choose a solution in which I assume setting the type is mandatory. Therefore if the type is absent - I fail fast. That would mean the Fragment was misused.
val type: String = arguments!!.getString("type")!!
The code above will crash if either:
a) arguments weren't set, or
b) String with type wasn't put in the arguments Bundle.
You are right, that is a : null ability issue.
First you should be sure if you are expecting a value, so try adding "?" or "!!", i would recommend "?", or go with the block of if {} else
To read the string safely you can use:
val type: String = arguments?.getString("type").orEmpty()
The orEmpty call at the end ensures that a valid String is returned even if either arguments or getString() returns null.
The method signature for getString() returns a nullable String. This is because at compile time, the compiler can't know if the value exists in the bundle or not. You will have the same issue when retrieving anything from any Map.
If you know for certain that the value in the bundle or map should exist at the time you call getString(), you can use the !! operator. That's what it's there for. When you know something should always be there, it is appropriate to want an exception to be thrown (in this case KNPE) if it's not there so you can easily find any programming error during testing.
isEmpty() or ?.let aren't helpful in this particular case because they would just be masking a programming error and making it harder to discover or debug.

Axon - How to get #QueryHandler handle method to return an Optional<MyType>

Note:
The point of this question is not to just getting back a value that I ultimately want.
I can do that by simply not using Optional.
I would like an elegant solution so I could start returning Optional.
Explanation of what I tried to do:
I used the QueryGateway with a signature that will query my handler.
I broke out my code so you can see that on my CompletableFuture I will do a blocking get in order to retrieve the Optional that contains the object I really want.
Note that I am not looking for a class that holds my optional.
If this is not elegant then I may as well just do my null check.
The call to the query works, but I get the following error:
org.axonframework.axonserver.connector.query.AxonServerQueryDispatchException: CANCELLED: HTTP/2 error code: CANCEL
Received Rst Stream
AXONIQ-5002
58484#DESKTOP-CK6HLMM
Example of code that initiates the query:
UserProfileOptionByUserQuery q = new UserProfileOptionByUserQuery(userId);
CompletableFuture<Optional<UserProfile>> query =
queryGateway.query(q,ResponseTypes.optionalInstanceOf(UserProfile.class));
Optional<UserProfile> optional = query.get();
Error occurs on the query.get() invocation.
Example of my Query Handler:
#QueryHandler
Optional<UserProfile> handle(UserProfileOptionByUserQuery query, #MetaDataValue(USER_INFO) UserInfo userInfo) {
assertUserCanQuery(query, userInfo);
return userProfileRepository.findById(query.getUserId());
}
The query handler works fine.
Other efforts such as using OptionalResponseType would not initiate my query as desired.
I think the key lies with the exception you are receiving Stephen.
Just to verify for my own good, I've tested the following permutations when it comes to Optional query handling:
Query Handler returns Optional, Query Dispatcher uses OptionalResponeType
Query Handler returns MyType, Query Dispatcher uses OptionalResponeType
Query Handler returns Optional, Query Dispatcher uses InstanceResponeType
Added, I've tried out these permutations both with the SimpleQueryBus and Axon Server. Both buses on all three options worked completely fine for me.
This suggest to me that you should dive in to the AxonServerQueryDispatchException you are receiving.
Hence, I am going to give you a couple of follow up questions to further deduce what the problem is. I'd suggest to update you original question with the response(s) to them.
Do you have a more detailed stack trace per chance?
And, what versions of Axon Framework and Axon Server are you using?
Are you on the Standard Edition? Enterprise edition?
Does this behavior only happen for this exact Optional query handler you've shared with us?

Interception messages in Squeak

I am trying to understand better reflection in Smalltalk. I am using the latest version of Squeak (v4.3). I want to intercept every message sent to instances of one of my classes. I assumed that I could override the method ProtoObject>>withArgs:executeMethod but Stéphane Ducasse explained me that for performance reason, this method is not used (this is my own summary of his answer). Which method should I override / how could intercept sent messages?
Here is the code of my attempt:
Object subclass: #C
instanceVariableNames: 'i'
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.
C class compile: 'newWithi: anInt
^(self new) i: anInt ; yourself.'.
C compile: 'withArgs: someArgs executeMethod: aMethod
Transcript show: ''Caught: ''.
^ super withArgs: someArgs executeMethod aMethod.'.
C compile: 'foo: aText
Transcript show: aText.
Transcript show: i.
Transcript cr.'.
C compile: 'i: anInt
i := anInt.'.
o := C newWithi: 42.
o foo: 'This is foo: '.
Executing this entire piece of code yields:
This is foo: 42
When I would like to have:
Caught: This is foo: 42
There's no build-in way to intercept messages to objects like that. There are two ways we commonly use to do this kind of trick.
First, you can create a wrapper object which responds to doesNotUnderstand:. This object usually has nil for the superclass so it doesn't inherit any instance methods from Object. The doesNotUnderstand: handler would delegate all its messages to the target object. It has the option of performing code before and after the call. All references to the original object would now point to the new "proxy" object. Messages to self wouldn't be intercepted and the proxy would need to test for objects that return self and change the returned object to be the proxy instead.
The second approach is to use a mechanism called Method Wrappers. Method Wrappers allows you to replace all of the methods in a set of classes with methods that do some other operations before and after calling the original method. This approach can provide fairly seemless results and intercepts all messages including those send to self.
MethodWrappers is available for VisualWorks and VASmalltalk. I believe it's also available for Squeak and Pharo but I'm not positive.
The three main techniques are:
Dynamic proxies
Method wrapper
Bytecode instrumentation
For a good comparision of all possible approaches, have a look at "Evaluating Message Passing Control Techniques in Smalltalk" by Stephane Ducasse (you already know him, apparently).
Of interest is also "Smalltalk: A Reflective Langauge" by F. Rivard, that shows how to implement pre- and post-conditions using bytecode rewriting. This is also a form of interception.

Class versus Instance method Obejctive-C calls - NSLocale methods

I am a very green nubie, anyways, I am working through a tutorial that walks me through using the NSLocale class to get the local currency, like this:
NSLocale *here = [NSLocale currentLocale];
NSString *currency = [here objectForKey:NSLocaleCountryCode];
NSLog(#"Money is %#", currency);
So, I understand that I am creating an instance of the NSLocale class called 'here', then I send the 'here' object a message asking for the objectForKey, and the result is returned into the NSString, called 'currency'. Last, I print the currency value with the NSLog.
Ok, so here's my question, I then reviewed what other methods are on the NSLocale class and I found one called 'preferredLanguages', it returns an array of the preferred languages. So I though I would call that method and then print it to the log, just for grins and to help me learn. Going off of the example above, I figured I would call it like this. Starting with the fact that I already have an instance of the NSLocale class called 'here' from the code above, I thought that I would just need the following ( I am repeating the three lines above just so it is easy to read here. )
NSLocale *here = [NSLocale currentLocale];
NSString *currency = [here objectForKey:NSLocaleCountryCode];
NSLog(#"Money is %#", currency);
NSArray *prefLangs = [here preferredLanguages];
NSLog(#"Preferred Languages are: %#", prefLangs);
But that didn't work, I got an error message that said, "No visible #interface for 'NSLocale' declares the selector 'preferredLanguages'
I figured out that I must do it this way instead:
NSLocale *here = [NSLocale currentLocale];
NSString *currency = [here objectForKey:NSLocaleCountryCode];
NSLog(#"Money is %#", currency);
NSArray *prefLangs = [NSLocale preferredLanguages];
NSLog(#"Preferred Languages are: %#", prefLangs);
I just don't understand why I had to call the method like this: [NSLocale preferredLanguages], instead of [here preferredLanguages]. The instance of 'here' is already created above. Can someone please explain.
You'll get accustomed to the joy and pain of Objective C pretty quick, but the short answer involves looking at the method declaration, which looks like:
+ preferredLanguages:
The "+" in the declaration indicates it's a class method.
Here's a relevant paragraph from Apple's "Learning Objective C" document
A class in Objective-C can declare two types of methods: instance
methods and class methods. An instance method is a method whose
execution is scoped to a particular instance of the class. In other
words, before you call an instance method, you must first create an
instance of the class. Class methods, by comparison, do not require
you to create an instance, but more on that later.
If the declaration starts with a "-", that makes it an instance method and you need to have an instance instantiated (created) in order to call methods on that object.
Hopefully this makes sense so far.

Resources