Ruby IntelliSense – the finer points
There’s quite a difference between analysing a Ruby program for IntelliSense and running it (as the Ruby interpreter obviously does). You do not want to run the Ruby interpreter at all when you are doing IntelliSense operations. Consider the (hopefully hypothetical) case where you are writing a Ruby program to re-organise your hard disk: you really, really don’t want to run it as you are editing it!
But there are more subtle points to consider as well. Approaching the problem as an implementation of the Ruby interpreter just doesn’t work. Consider the very simple example below – IntelliSense correctly reports that the two methods for the object y are x and the singleton a. By the way, note the different “completion set” icons representing a singleton method and a public method. I’ve recently got that working and I’m quite pleased with the result. Now let’s set y to be a string
y = “hello”
So what’s the IntelliSense scoop now? Well, it’s here: You can see that the result is correct for a string . Moreover, it does not display any of the methods of an X. But this hides a good bit of work. I have to keep track of two versions of y – one that is of class X and the other of class String. The Ruby interpreter doesn’t have to do this. Once it hits the second assignment, it ‘forgets’ about the first – it has no memory that y was once an X. I don’t have that luxury – I must keep track of the two y’s. Otherwise, the IntelliSense will be wrong depending on where you are in the file - not desirable at all.
In C# (say) you don’t have this problem. A y of class X is always an X at least within the same scope and leaving aside generics – all you have to do is keep a pointer to the definition of y. And as I’ve pointed out, the Ruby interpreter doesn’t care.
I came across a post somewhere on a newsgroup asserting that to do Ruby IntelliSense would take a program of at least the complexity of the Ruby interpreter itself. I think that this simple example shows the truth of that statement!