Code Completion in Dynamically-typed Languages

Code Completion is a nice IDE feature that, for example, shows a list of methods for an instance of an object. It’s called IntelliSenseWP in Microsoft Visual Studio WP; in XCodeWP it’s just called “Code Completion”. It’s a very fast and user-friendly way to look up methods — while editing JavaWP in XCode, as soon as the user enters a period after a variable name, a list pops up, and as the user types it continues to narrow it down based on the first few letters. Documentation may also be displayed.

While XCode and most Java and .NETWP IDE‘sWP support this well, it’s a bit more difficult to implement for dynamically-typed languages like PythonWP and RubyWP. This is because of the difference between dynamic and static type systems WP. In a static type system, the type is determined at compile time, so the IDE can compile the code on the fly and find out the type. In a dynamic type system, the type is determined at runtime. Since running code can make changes to the system, such as deleting files, code can’t simply be run by the compiler to find out the type. Also, the type of a variable can vary, depending on a program’s input.

IDE’s for dynamically-typed languages implement Code Completion by examining the code. In a dynamic language, however, it’s impossible for an IDE to make a perfect guess as to which type a variable will be, in a given line of code, or which of several types it could be. It’s possible to let the user tell the IDE what type it’s expected to be. By guessing what type a variable has and letting the user override the guess, an IDE can have pretty good Code Completion for a dynamically-typed language.

One issue is, however, how does the IDE remember the user’s setting? Is it in a project file? I don’t really like having information for a file stored in a project file, since when the file moves between projects, settings are lost, or you have to go through the IDE’s way of moving the file between projects. Another possibility would be using a dot file (e. g. .foo.rb.ide-options) in the same directory. This is the way jEditWP stores bookmark settings. I don’t like this option because since they’re hidden I’m always forgetting to move them, and because it’s a pain to delete both the file and the bookmark file at the same time (I don’t like typing something like rm *foo.rb* because it will include baz_foo.rb). That leaves a couple options – including it right there in the source file or using a different naming scheme. This is easy to move around, but I’d rather keep these mundane details out of the source file.

This leaves using a different naming scheme. Perhaps foo.conf or foo._name_of_ide_. Whenever python runs a module, if it can, it automatically compiles it to bytecode and places it in a file with the same directory and name but with a different extension (pyc vs. py). I find that I have no problem with .py and .pyc showing up in my source directory. It’s nice to know that it’s byte-compiling it, and it’s easy to move around and delete (just use a wildcard expression like foo.*).

There’s no reason the metadata file can’t include all kinds of other things. I would want it to be extensible, and to include such things as bookmarks as well as Code Completion hints. This information could be stored as XML, YAML, or (my favorite) an S-Expression. Perhaps limiting it to things that only happen in the IDE would be a good idea, or maybe it could include instructions to the compiler to improve performance as well.

Another thing needed is a way to identify a variable inside a source file. I think the most elegant way would be a path containing the scope it’s in and the name of the variable. This would be something like my-namespace/my-class/my-method/param/bar. In an S-Expression format with the type and a construct for entering several in the same scope it could be something like:

(with-scope 'my-namespace/my-class/my-method'
  (specify-type 'param/p' 'Person')
  (specify-type 'local/brother' 'Person')
)

This would declare the parameter my-method and the local variable brother to be of type Person.

Finally, a quick way to declare the type in the IDE would be useful. I would like a right-click menu that goes something like this:

Popup Menu
+(other options…)
+Code Completion Type
++Auto
++(recent options)
++Custom…
+(other options…)

The Auto option would go back to having the IDE guess the type of the object. On a related note, I really like “auto” options that there are in office applications. It makes it really easy to say whether you want to stick with whatever the parent options are or specify your own options.

I have visions of a Lisp dialect with a great library and a great IDE getting a bit of a following and creating lots of LISP jobs. I think good support of code-completion while still having run-time typing, a dull color for parens, and built-in performance analysis WP tools (as Paul Graham suggested) would generate a lot of interest.

Thanks to Eliazar for the idea of using superscript to link to Wikipedia and other online resources.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.