NSUserScriptTask: accepted file types? - objective-c

I'm using NSUserScriptTask to run scripts the user placed in the Application Scripts directory. However, I'm finding it hard to find out which are the known types of scripts that NSUserScriptTask accepts and the docs don't help much either... Any ideas?
So far I've tried these:
.sh
.applescript
.scpt
.scptd
.txt
And coudn't get any of them to work (the initWithURL:error: method returns nil)
EDIT:
I forgot to include the error! Silly me... Here's what gets printed on the log:
Error Domain=NSCocoaErrorDomain Code=259 "The file “Untitled.applescript” couldn’t be opened because it isn’t in the correct format." UserInfo=0x100121f50 {NSURL=file://localhost/Users/path to file/Untitled.applescript, NSFilePath=/Users/path to file/Untitled.applescript}

The documentation for NSUserScriptTask claims that instantiating that class directly will work on any valid file and return the appropriate kind of task:
The returned object will be of one of the specific sub-classes (NSUserUnixTask, NSUserAppleScriptTask, and NSUserAutomatorTask), or nil if the file does not appear to match any of the known types.
If invoked from a subclass, the result will be that class or nil.
In reality, I found that (as of 10.8.2) NSUserScriptTask unconditionally returns nil and a “what is this i dont even” error. It seems that you need to instantiate the correct task subclass yourself. Probably worth filing a bug.
To test whether a file is usable as a script task (e.g., in an Open panel validation method), all I can suggest is to try instantiating each of the three classes, returning YES if any of them succeeds and NO if all of them fail.

Related

Are ByteBuddy's field setting checks too strict?

I am using MethodCall.setsField() to try to set an instance field on another instance.
My generated class that is doing the field-setting, GC, is trying to set the value of an instance field in an instance of something it has created (CI). So the field's declaring type is CI; my field-setting code resides in GC (which is in the same package as CI but otherwise unrelated to it).
The ByteBuddy checks seem to indicate that although GC and CI are in the same package, GC must be assignable to CI in order to set this field! That greatly surprised me, but I am not a bytecode expert, and I might very well be overlooking something obvious. Could someone kindly explain why this check is necessary?
The method call sets the field implicitly on the this instance on which the method is invoked. For this to be possible, a non-static field must be declared by a super type of the type on which the method is invoked.
If you think this is too strict, please file an issue with an example of the code you are trying to generate, including the code to generate it which is currently failing. Maybe I am not thinking straight about this and if there's a restriction to be lifted, I would surely do it.

More than one coder for gwt autobean causes AssertionError

When deserializing an autobean from JSON I get an AssertionError from com.google.web.bindery.autobean.shared.impl.AutoBeanCodexImpl.CoderCreator#getCoder. Looks like there are two types registered for my autobeans:
my.project.model.MyAutoBean
java.lang.Class
Of course I find the second one quite useless but I don't know where it comes from and how to get rid of it. When I disable assertions the code just works fine and (de)serializes my Autobean perfectly.
I already get two types in the initialization of the ClientPropertyContext but I cannot debug what in MyAutoBean.traverseProperties is happening.
I found it out on my own:
My autobean interface was extending another interface that had a method to return the AutoBean's class (to work around java type erasure in a facoty method). After removing this method it worked.

Is there an efficient way to avoid instantiating a class with syntax errors?

As you may know, it is pretty easy to have active code of a class containing syntax errors (someone activated the code ignoring syntax warnings or someone changed the signature of a method the class calls, for instance).
This means that also dynamic instantiation of such a class via
CREATE OBJECT my_object TYPE (class_name).
will fail with an apparently uncatchable SYNTAX_ERROR exception. The goal is to write code that does not terminate when this occurs.
Known solutions:
Wrap the CREATE OBJECT statement inside an RFC function module, call the module with destination NONE, then catch the (classic) exception SYSTEM_FAILURE from the RFC call. If the RFC succeeds, actually create the object (you can't pass the created object out of the RFC because RFC function modules can't pass references, and objects cannot be passed other than by reference as far as I know).
This solution is not only inelegant, but impacts performance rather harshly since an entirely new LUW is spawned by the RFC call. Additionally, you're not actually preventing the SYNTAX_ERROR dump, just letting it dump in a thread you don't care about. It will still, annoyingly, show up in ST22.
Before attempting to instantiate the class, call
cl_abap_typedescr=>describe_by_name( class_name )
and catch the class-based exception CX_SY_RTTI_SYNTAX_ERROR it throws when the code it attempts to describe has syntax errors.
This performs much better than the RFC variant, but still seems to add unnecessary overhead - usually, I don't want the type information that describe_by_name returns, I'm solely calling it to get a catchable exception, and when it succeeds, its result is thrown away.
Is there a way to prevent the SYNTAX_ERROR dump without adding such overhead?
Most efficient way we could come up with:
METHODS has_correct_syntax
IMPORTING
class_name TYPE seoclsname
RETURNING
VALUE(result) TYPE abap_bool.
METHOD has_correct_syntax.
DATA(include_name) = cl_oo_classname_service=>get_cs_name( class_name ).
READ REPORT include_name INTO DATA(source_code).
SYNTAX-CHECK FOR source_code MESSAGE DATA(message) LINE DATA(line) WORD DATA(word).
result = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
Still a lot of overhead for loading the program and syntax-checking it. However, at least none additional for compiling descriptors you are not interested in.
We investigated when we produced a dependency manager that wires classes together upon startup and should exclude syntactically wrong candidates.
CS includes don't always exist, so get_cs_name might come back empty. Seems to depend on the NetWeaver version and the editor the developer used.
If you are certain that the syntax errors are caused by the classes’ own code, you might want to consider buffering the results of the syntax checks and only revalidate when the class changed after it was last checked. This does not work if you expect syntax errors to be caused by something outside those classes.

When is class side initialize sent?

I am curious about when the class side initialize messages are sent in Smalltalk (Pharo and Squeak particularly). Is there any specified order? Is it at least safe to assume all other classes packaged with it have already been loaded and compiled, or does the system eagerly initialize (send initialize before even finishing loading and compiling the other classes)?
The class-side initialize is never sent by the system. During development you do it manually (which is why many of these methods have a "self initialize" comment.
When exporting code of a class into a changeset, the exporter puts a send of initialize at the very end, so it gets executed when the class is loaded into another system.
This behavior is mimicked by Monticello. When loading a class for the first time, or when the code of the initialize method was changed, it is executed. That is because conceptually MC builds a changeset on-the-fly containing the difference of what is in the image already and what the package to be loaded contains. If that diff includes a class-side initialize method, it will be executed when loading that package version.
As you asked about loading and compiling, I'm assuming you mean when loading code...
When loading a package or changeset, class-side #initialize methods are called after all code is installed (1). While you can not count on a specific order, you can assume that all classes and methods from that package are loaded.
As Bert pointed out, if you were not loading but implementing class-side #initialize, you'd have to send the message yourself.
One way to know for sure, is to test it yourself. Smalltalk systems make this kind of thing a little more approachable than many other systems. Just define a your own MyTestClass, and then implement your own class side (that's important) initialize message so that you can discover for yourself when it fires, how often it fires, etc.
initialize
Transcript show: 'i have been INITIALIZED!!! Muwahahahah!!!'
Make sure it works by opening a Transcript and running
MyTestClass initialize
from a Workspace. Now you can play with filing it out and back in, Monticello loading, whatever and when it runs.

Duplication of interface error in xcode

I am not even sure how to start.
I am developing an iPhone application with the latest Xcode and sdk using core plot and the core async socket library. Everything was fine until a few hours ago, when Xcode dumped a ton of "interface duplication" errors for no apparent reason.
The two files that are emitting errors are the AsyncSocket.h and an API client that I wrote in order to get data out of the target server.
The errors are the following:
Nested Redefinition error on all enums in AsyncSocket.h and my API client.
Redeclaration of enum on all enumerations in AsyncSocket.h and my API client.
Duplicate interface declaration on the AsyncSocket.h and the API client's interface file.
The error occurred between two builds of the application. NOTHING was changed during that time which is why I can't even begin to think what is causing this.
The API client is a really simple thing, it just uses the async socket to send queries to the server and then return the parsed results in arrays. Nothing complicated, as I am not that into objective c yet.
I wish I could give some more useful information but that is all I have.
i believe your problem results from a simple mistake. In the header file you begin with:
#interface ClassName : SuperclassName
while in the .m file you do:
#interface ClassName ()
When you forget the brackets, the compiler complains.
I hope this helps. Best wishes with your app.
I had this problem and the response above put me on the right track.
I created a new enum record in a .h file I use for all my Constants.
But I forgot to add the semi-colon on the end. This simple little syntax error resulted in some weird and confusing errors appearing on files other than the one which contained the error.
No doubt you've resolved this by now but it might fix someone else's issues in the future.
I also experienced the "Duplicate interface definition" error message and traced it to my having put an "#include xxx.h" in a header (.h) file instead of in the .m file where I intended to put it.