Seva's notes

Wisdom, Awareness, Responsibility :)

Grouped Completion (Content Assist) in PDT

with 2 comments

Last Wednesday I was working on grouping of code completion (content assist) options. It’s now only exists in CVS and will be (hopefully) released with the build after the next one (the current is already finalized).

Overview

The main point of the feature is collapsing of multiple same-prefixed options into groups, instead of showing a long list of the options. For example if your application is based on Zend Framework or PEAR, most of library’s classes start with “Zend_” or “PEAR_”, and this is what you will get as a completion option. In addition, the grouped list doesn’t show common prefix if an user already typed it.

(Demo)

In general it’s applied to all the types of elements (classes, functions/methods, variables and constants) in all the possible contexts (general completion, doc blocks, new/instanceof etc.). The feature is disabled by default can can be found at:
Preferences->PHP->Editor->Code Assist->Group Completion Options

The logic of the grouping is very similar to completion of files in include statements in Zend Neon and is quite simple:

  1. If there are several options which share common prefix AND there are additional elements which do NOT have this prefix, the sibling elements are collapsed to groups with “…” suffix.
  2. After completion of a group, completion pops up immediately again to show elements with the typed prefix.
  3. If typed prefix has common prefix with proposed elements/groups, it’s collapsed with “…” prefix.

How it works

First, all the types of code completion options are created by objects which extend an abstract CompletionProposalGroup (View Source). The class’ work is to receive an array of CodeData‘s and return an array of ICompletionOption‘s. This is why the feature’s code is mostly aggregated in this class.
So, instead of just creating a completion option for each element, we should first create a tree of all elements, based on elements’ name chunks separated by “_”, then go over the tree and extract only the relevant elements and groups, and then create chopped completion options for groups and elements. And now in details –

Creating Tree of Elements

CompletionProposalGroup.buildCompletionTree()

Luckily, Eclipse platform provides two base components which made the implementation relatively simple. It’s IPath/Path couple, which provide a comfortable solution for handling abstract OS-like paths, and ElementTree, which is a recursive tree data structure which gives access to it’s nodes based on IPaths.
The first action item here is to create a path from element’s name – it’s done by replacing all delimiters with slashes and providing the result string to Path‘s constructor. Then it’s time to recursively create the element – if the parent path is not in the tree, we’ll add it with null data attached (these nodes will represent element groups in the future). After the parents exist, we are adding the element itself to the tree with CodeData object attached.

Extracting relevant Elements and Groups

CompletionProposalGroup.treeRecursiveCreateElement()

In order to get the relevant elements and groups according to 3 rules mentioned above, we basically need to recursively get children of a tree node starting from the root. However if there are no children for current node or the node has sibling(s) – we don’t want to continue deeper inside, and just return the current node. As a result, we get list of elements and collapsed groups to create completion proposals from.

Creating Elements and Groups Completion

CompletionProposalGroup.calcCompletionProposals()

Afterwards, the only remaining thing is to create proposals. For element proposals there is a wrapper proxy PartialProposal for CodeDataCompletionProposal which cuts off matching segments of prefix, and for groups – there is a wrapper proxy TemporaryCompletionProposal for CompletionProposal created with cut prefixes,  which only ovverrides ICompletionProposal.apply() method to reactivate completion immediately group application.

That’s all it’s about.

Written by Seva

2007-11-25 (November 25) at 06:52:43

2 Responses

Subscribe to comments with RSS.

  1. Hi Seva,

    I am using PDT (and PHP) for the first time. I’ve been a J2EE developer so far. I thought you could help me a bit. Hope you would not mind.

    1. Is there any good reference that compares standard Java frameworks (struts, spring) to symfony? I can get ramped up quickly this way.

    Seva: I never used J2EE frameworks, so I can’t help you with this. Sorry.

    2. Content assist is not working in my Eclipse PDT. I am using standard symfony directory structure. Do you have any idea how to troubleshoot this?

    3. We are using an Ubantu server to test the app, and not using local setup on windows desktops. We sync the code every time before testing it. Can I setup a debugger (say Xdebug) on the dev server and link it with my local code?

    Seva: Regarding these two questions you should explore archive of PDT news-group. These questions were asked and answered more than once.

    Hope you can help… 🙂 so thanks in advance…

    Sumedh

    2008-02-28 (February 28) at 09:05:39

  2. Hi Seva,

    Thanks for the reply…

    I checked out the newsgroup…but there is nothing much…there is a thread that asks to see the log…I dont see anything in the log when I press ctrl+space…it just doesn’t respond…

    and actually, my content assist was working fine till couple of days ago…but after I’ve made some changes in directory structure, it doesn’t work…

    Does it have anything to do with Errors? Because I see whole lot of HTML errors…(which are wrongly seen as errors by eclipse…like closing tag is present in some other file, but eclipse doesnt see it)…

    If you could mail me at my email, I’ll be very thankful…

    Seva: it’s better for all of us if you will ask the question in the News Group.

    Sumedh

    2008-03-01 (March 1) at 12:13:23


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: