NetBeans Screenshot of the Week #41: Type Assertions


Python and Ruby are dynamically typed languages. We have a lot of heuristics in our editors to figure out the types - tracking assignments, analyzing your database migrations, etc - to help code completion, go to declaration and other IDE features work correctly. And Martin Krauskopf, who owns the Ruby editor now, has been improving the type inference for Ruby a lot lately.



However, there are cases where we just can't help. What if you're writing a brand new method you haven't called from anywhere, and you're trying to access methods on one of your parameters? We don't know the type of the parameter. In that case, NetBeans will provide "fallback code completion" - it will list ALL methods across ALL known classes in your project, libraries and current platform.



If you're looking for the documentation or parameters for a specific method - that's useful - after typing 2-3 characters you've typically narrowed the result set down to a handful of methods and you can pick the one you're looking for.



But what if you're not sure what the method is called? That exact scenario happened to me a couple of days ago. I was writing some Python code to do some string manipulation, and not being very familiar with Python I wanted to know what the equivalent of Java's indexOf method was in Python. I knew that the parameter in my method was a String, but I didn't have a way of telling the IDE that. I applied my usual workaround of adding a line above the current call:


x = ""

and then I could invoke x. to see the methods available for a String. However, that's definitely not a good way to do it. What if I forget to remove my fake assignment? (Yep, I did that too. I couldn't figure out why my code wasn't working until I debugged and realized I was clearing out the parameter with a bogus assignment... Doh!)



The "obvious" solution for this is supporting type assertions. We've had those for a long time in the Ruby editor
(picture), and obviously for JavaScript using the @type and @param {type} syntax. And the PHP editor just added support for type assertions as well (more here and here).



I've just added this for the Python editor as well. But I've gone one step further which I think makes the feature much more obvious, and easy to use. In code completion, if the editor detects that you are attempting to complete on a simple variable (as opposed to for example a complicated expression), and the type of that variable cannot be resolved, then we add a new special code completion item at the top of the list. Here's what it says (and a more detailed explanation in the documentation popup):







As soon as you press enter, the IDE will insert a special comment referencing the variable you were completing on, and automatically invoke code completion again to complete on the type statement:







The contents of this list has two parts: First, it lists the pseudo-types for many of the core builtin types, like ints, strings, lists and tuples. After that it will list all the known types in the system, such as the user and library classes. If you select one of these and try code completing the original expression again, you can now see that the type resolver knows what to do:






A couple of notes about this. First, note that the type assertions are just comments in your source. You can delete them - they are merely an aid to the IDE. Not only code completion uses these - go to declaration for example will also be more accurate if it is explicitly told the type of a variable it cannot figure out. You can also use multiple type assertions within a method in case the variable type changes during the method. This isn't the case with Ruby yet; the type assertions apply to parameters only, at the method level. But Martin has promised to look into this for Ruby as well so hopefully there will be full parity between the two editors shortly!



P.S. Just like in the PHP editor, mark occurrences and instant rename are type-assertion-aware:




Comments:

great little features added to the netbeans python plugin, i was really glad to see you on the wagon of people working for python editor as well...and you blogging about these new features and providing so many screenshots to go with all the words :)
after seeing so many nice things going into the ruby editor, and the javascript editor, made me want even more for a python plugin to also come to netbeans.
It's a great thing you guys are doing with this python plugin and i can't wait to see what other new features and functions are going to be implemented in the python editor, pydev needs some healthy competition

Posted by dave on January 13, 2009 at 04:18 AM PST #

Another IDE, I forget which, uses manually inserted asserts

assert isinstanceof(s, basestring)

to get type info which is a different approach for this. Each has it's merits. I'd be more willing to accept this form in a team environment rather than comments which can go stale much easier.

Posted by Manpreet Singh on January 13, 2009 at 11:28 AM PST #

Hoo-ray! If this is added to the Ruby editor, there will be no question as to the best ruby ide IMO.

Ideally it would be possible to set an option to not actually insert the comment but rather to remember the type for some logical temporal scope.

Posted by James on January 13, 2009 at 12:41 PM PST #

> What if you're writing a brand new method you haven't called from anywhere, and you're trying to access methods on one of your parameters?

Of course, if you're doing TDD then you've already written tests for the method :-)

Posted by Michael on January 13, 2009 at 08:30 PM PST #

Any chance of adding extra annotations for return types of methods? There are both complex and simple cases here. But at least including it for the simple cases should help out some on code completion. Something like:

# @type someMethod list
def someMethod():
return []

Posted by Ståle Undheim on January 13, 2009 at 09:21 PM PST #

I think it should accept defining type information in doc string other than comment.

Posted by sgwong on January 14, 2009 at 01:08 PM PST #

I didn't see this in the wiki (http://wiki.netbeans.org/Ruby). Would be good to get this in a one of the listed features...

Posted by GregH on January 15, 2009 at 06:46 PM PST #

A common was to import packages is to use the syntax "from base import package". However Netbeans does not recognize the type of "package" when attempting to auto-complete and the assertions don't help there.

It does however give correct completion when the import syntax used is the following: "import base.package as package"!!

Fixing this issue would make it to possible to use Netbeans for django projects.

Keep up the good work!

Posted by Gautam on January 16, 2009 at 04:50 PM PST #

This is pretty cool, and I didn't even know about the comment-based type stuff for Ruby. We should try to publish a document for this syntax and formalize it...then we could in JRuby even start to take advantage of type assertions in a similar way to Groovy.

Posted by Charles Nutter on January 19, 2009 at 03:44 PM PST #

Hi,

Great article.
I've searched all over the place where to post my question about nbpython's auto-completion but your blog is the only place that seems to be the only place (I can't figure out how to sign up for the mailinglist).

Anyway, maybe you could answer my question why does this:

==============
from django.db import models
models.<CTRL-SPACE>
==============

result in one enormous list with all objects NB seems to find on the python path, while this:

==============
from django.db import models
django.db.models.<CTRL-SPACE>
==============

results in a short list with only relevant items.

Thanks!
Berco Beute

Posted by Berco Beute on January 22, 2009 at 07:18 AM PST #

Hi Berco,
that looks like issue 156984:
http://www.netbeans.org/issues/show_bug.cgi?id=156984
(Gautam also reported this - perhaps you're the one who filed issue 156984?)

I just integrated a fix for it.

Regarding all the type assertions related comments: I did add support for the "assert isinstanceof(s, basestring)" syntax last week. However, at least in Ruby this was very controversial; when you put type assertions into your code it becomes part of the contract, as opposed to hints to help the tool resolve variables etc. Ditto when you add the types into the actual docstring itself.

Ståle - yes, we definitely need to be able to annotate return values too. We have support for that in JavaScript, but in the Python support we're not yet computing types through expressions with calls.

Posted by Tor Norbye on January 22, 2009 at 09:26 AM PST #

Hi Tor,

Thanks, that looks indeed like that issue.

Sorry for asking this here, but now I'm wondering how to get the latest Python-Netbeans version. The latest zip on the site doesn't contain Python support. Do you have any idea where to get that?

Thanks!

Posted by Berco Beute on January 26, 2009 at 05:07 PM PST #

Hi Berco, try

http://deadlock.netbeans.org/hudson/job/python/

Posted by Tor Norbye on January 26, 2009 at 10:25 PM PST #

Post a Comment:
Comments are closed for this entry.
About

Tor Norbye

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today