LabelProvider improvements

Greetings,

Since I tried to get involved in the DDT project I always wanted to improve the label provider section. Though Bruno did not merged my changes much in to the main line, but it seems it inspired some changes since then. One of the painfully missing thing was the visual aid of the elements’ protection level. The reason why the merge did not occur before is that it supposed to be shown as an overlay.

I opened a feature branch to improve the label provider, and my first step was to show the protection level icons. Now, as I don’t think it is wise to use completely new set of icons, neither I’m a talented graphic designer, I took the JDT’s protection level icons and applied as an overlay on all elements except of functions and variables. The variables/fields and methods/functions are treated similarly to JDT, they get a completely different icon. If this is still unacceptable, I’m willing to add an option where it could be set to use the original method/field icons with overlay in normal mode, and a “JDT-style” which would work as I described above.

The only issue with the solution that I had to modify the ScriptElementImageDescriptor_Fix class in order to make it more flexible. I don’t think it is a bad choice, but I recognize that it could pose a problem with the integration to the DLTK 4.0. But if it comes to that, I will fix it anyway.

It would also be nice to have the return type description with different color but that’s gonna be an other story.

You can find the branch here. Also, here’s a screen shot, how does it look like:

Time for tidying up

As Bruno posted the contribution guidelines it is time to clean up the mess I made and separate the different features from the master branch and from each other. I’m afraid it won’t be easy given that my public master branch was already littered with these feature fragments.

First I have identify the unrelated commits in the history in order to determine the new feature branches. I was working on several problems and most of them isn’t ready to be merged to the main development line.

  • ANTLR parser. This feature involves the AST classes, removing the old ANTLR thing, and adding the new ANTLR grammar. A potential issue could be those constructor codes that was added in the type-inference branch which I integrated in to the master for accessing those modifications.
  • The D Element label provider. This feature aimed to bring a more JDT-like icon set in the necessary places, such as the Outline view, the Script View and the completion proposal list. I found that basically this is not much more than one commit. There was also a hack to get the module name in a module definition label, but I’m quite uncertain of that change. However, this is a complication as I submitted that change in a random time, so I can’t use a range of commits to separate it out. Perhaps if it is easy to do, I should just simply get rid of it. This feature would add new icon files and change the DeeModelElementLabelProvider class.
  • Static library support. Now this is a worthy feature that is the closest to being completed. However, the issue mentioned above would make it complicated to separate to its own branch. After the separation I should request Bruno to have a look on this feature. The affected code is the builder, the project preferences and spreads to places like DLTKModuleResolver in the core.parser package. The change sets are ranging from here to there.
  • Bracket inserting. Should be quite straightforward as it is only one commit.
  • Type inference. The code that was submitted on this feature does nothing really interesting at the moment. It contains some key refactorings however that probably should be used later for many reasons. One of them is to have a visitor structure that is sufficient to work with all AST class and the other is replace the getMemberScope() (and later probably other AST member-) methods with visitor based processing code. The actual type inference code is only exploratory, trying to integrate the dltk’s type inference basics as an entry point code.
  • Renewing the completion proposal collecting code. The visitor refactoring above could be potentially useful for collecting completion proposal and would be better than the existing code as it is quite obscure. This completion proposal system should be aware of the priority listing, keywords, templates, and all resolvable nodes, not just references. The latter means that completing members for expressions (such as, casting an object or so). Should contain the changes in the function definitions but it is not working at the moment (the feature that the argument list is pre-filled with the parameter names and working like the template suggestions).

At the end of the day, I had to explore the weird world of rebasing as I did not really bother to learn it before. It’s because every time I’ve encounter with it, there was always a note that it could mess up things pretty badly,  and some even says that it is like lying.

Rebasing in git is like to take a range of commits and “replay” them on the top of a branch or a specific revision. This is the perfect tool for the job I am about to perform. The work flow is like this: take the deviation point in my master branch, pick those commits that are relevant to the functionality, and apply them on the deviation point it self. Sounds almost too simple.

However, there are problems that I need to be aware. One is the problem with rewriting the history: I can’t re-base a tacking branch and expect that I can push it easily to its remote. Once I push a branch somewhere re-basing it is not an option anymore. So if that happens, and I screw up (like this happened with the first attempt to do this with the feature-static-library branch where I included commits that renders the branch virtually impossible to merge to bruno’s master), there’s no way back. The only thing I can do, if nobody hangs on my repository, that I wipe out the whole stuff and push the necessary branches from scratch. At the end of this exercise, this is likely to happen though. The only person I share my repository is bruno, and he doesn’t depend on any of my current branches.

That pesky file name capitalization is really annoying. If I want to switch to a branch that has the previous file name, I have to delete the file to get rid of the problem. Not only that, I ran in to this while I performed the rebase call, which is even more annoying as I have to fix to the right name with an additional commit.

Finally I mastered the rebasing so now there’s a new repository I’m working with. There are three feature branches so far: feature-static-libraries, feature-labelprovider-improvement, feature-antlr-parser. These branches were grown from the latest master from Bruno, so there should be no problem to merge them in to the main line.

LL(k) -> ASTNeoNode

I was working recently on an ANTLR based parser for the DDT project. As a phase 1. I’m trying to get the current AST hierachy working under this new parser without having to rely on the Descent parser. It isn’t finished yet, but it is at the level of progress where it worthy perhaps for other to look at it. To see what is missing here’s my sketchy list:

  • Missing import expression node in the AST
    import expression : ‘import’ ‘(‘ assignExpression ‘)’ ;
  • Clarify the function literals
  • Missing static if expression.
  • Missing static assert expression.
  • How to deal with conditional statements (version, debug, and such)?
  • Struct initializer must be implemented.
  • What is ExpIftype is for? Is that something to do with the template stuff? Or static if?
  • IsExpression in the AST somewhere? (It’s pretty tough expression btw).
    isExpression
    : is ( Type )
    | is ( Type : TypeSpecialization )
    | is ( Type == TypeSpecialization )
    | is ( Type Identifier )
    | is ( Type Identifier : TypeSpecialization )
    | is ( Type Identifier == TypeSpecialization )
    | is ( Type Identifier : TypeSpecialization , TemplateParameterList )
    | is ( Type Identifier == TypeSpecialization , TemplateParameterList )
  • Template declarations are missing in the parser rules.
  • Template instances are missing in the parser rules.
  • Proper attribute specifier implementation. (That is, accumulate all the attribute specifier to the corresponding definition).
  • Error handling and error recovery resembling to the Descent’s parser’s one.

The actual state is on my clone’s master branch here:
http://code.google.com/a/eclipselabs.org/r/gyulagubacsi-ddt-root/sour…

As I try to replace the current parser without changing much of the current state of the code (I made very few, the most obvious
modifications, such as constructors for creating AST nodes without the conversion process, and in very few places I added extra fields to currently existing nodes.), I wouldn’t add at this point any new features, or mess with the AST hierarchy.
This is my first try to create parser with a parser generator, and I admit, many places there’s need to improve the current state. Later on, we should change the ASTNeoNode hierarchy to work with on the CommonTree ANTLR object, which would eliminate the need for individual object creation as an action code. (Not sure completely how, but I think it is possible to create heterogeneous trees with ANTLR using factory pattern which in turn would need the ASTNeoNode classes and
interfaces to be more consistent as they are today. As an example of inconsistencies, at the current state some nodes are using ArrayView, others use simple arrays of objects, and so on.

Under The Bonnet: Parser, Lexer… ANTLR

Sometimes it goes like this: you start to make your well defined contribution (type inference), and as you start to assess the job to be done, you realize that some parts are bigger than you thought. So you start looking in to them time to time, and only after a while you realize that you’re step further down in the heart of the project. At this time, I fell in to the parser but for a reason: At work, I was working on a toy parser for a server with the good ol’ hand-crafted way. And I found it fun. Originally, I had the idea to  use bison, ANTLR or something similar to generate a parser, but I rejected the idea because I was afraid I couldn’t learn enough about the compiler generators to finish my task in reasonable time.

In the recent weeks, I tried to get my head around the core of the DDT.  I’ve found the current visitor accessibility unfortunately narrow for semantic analysis, type deduction or type inference, and ran in to some artefacts in the AST design. Well, this is always good news as someone has to deal with these issues. Soon enough I found that the lack of direct parser to our AST is a source of unnecessary complexity, not to mention the possible overheads. I say possible, because I couldn’t make my self carry out detailed measures. OK, OK, I’m lazy! Anyway, so the obvious choice was to look in to the question of the ANTLR parser.

Some initial experiments taught me that I shouldn’t follow Walter’s BNF-kinda description because 1. it is heavy of left-recursive rules definitions, which needs serious re-factoring, 2. there are too many differences between our current AST hierarchy and D documentation’s for explaining the language.

Static Library Support: Project dependency to static libraries

Last time I was dealing with the project build types that allowed DDT to produce static libraries out of a project. That’s a vital element for a larger project infrastructure so its implementation should be priority. This time there was an other problem related to the larger projects. It’s all nice and good to have lib files produced but we couldn’t really do anything with them at all.

Actually, the same way as most of my development I heavily relied on what Bruno did before. As far as I understood the already existing code the heavy lifting was already done. That is, the project dependencies on libraries were implemented as a skeleton, only that it wasn’t useful… yet. The only thing left to implement is to use the project dependencies’ output (the static libraries themselves) as input modules and their source directory as input directory on the referee project. But nothing is as easy as it looks. I’ve just encountered a quite disturbing fact: the DLTK documentation is just virtually non-existent. There are some vague articles in their wiki, but the API documentation is basically isn’t any useful. That makes life quite hard to develop anything on the DLTK basis and frankly I’m worried about the scenario when DDT hit huge problems with the DLTK. The actual issue I encountered looked quite easy: how can I get libraries from a different project and resolve their paths relative to the workspace. At this point of time I didn’t find anything useful for this. So at the time being I had to hack the references to other projects with a simple “../[projectname]/src” as an  import directory and “../[projectname]/lib/[projectname].lib” as a input file. But the real solution would be to get access to the other project DeeBuildOptions object which could provide me the necessary settings for the output file, its build type from its IScriptProject info the source folders as they could be more than one.

In other words, to use this new feature the user has to make sure that the directory structure is that of the default and there are no additional source folders. Also it probably won’t work with anything but DMD and possibly only on Windows. The next target is to eliminate these problems.

The corresponding change set in the source code: r341098a21488

 

Static library support

After some messing around the EGit finally I came to understand how to push my changes to the google code clone. It came as a surprise because I was sure that I understand the git architecture. The problem was that I had proper ref specs to the google code clone’s repository.

Today’s exercise was to add some support of static libraries. I found that the DeeBuildOptions class had some traces for supporting different build types but it was set to EXECUTABLE without the option to change it. In the case of static library, the DMD compiler offer an option “-lib” to build static libraries. In addition I found that the there were already a combo box to set the build type in the DeeProjectOptionsBlock which is responsible for handle the compiler options in the UI.

So this part of the job was pretty easy: Uncomment the relevant part in the DeeProjectOptionsBlock.createControl method that shows the combo box for the build type setting. To handle the default cases better than we do currently, I hid all the properties of the DeeBuildOptions class and added some handling of the default values. If there’s no set output directory yet, it will depend on the build type, for instance: if the build type is executable or dynamic library, the output directory is ‘bin’, if the build type is static library, the output directory will be the ‘lib’ directory. However, I noticed a tiny little problem here. The D programming language is a native language which means that the compiled modules are subject of linking. That is, the real output of the build process is the executable/library/dynamic library and the object files themselves are kind of a by-product of this process. Most of the build system I saw there were a separation between the intermediate files (object files) and the final output. As a next step I would like to add an intermediate directory for the object files to handle (of course, if the user wishes so, he can keep the output files mixed with the object files).

On the UI with small little hack I only update those DeeBuildOption fields that were actually edited so that my changes on the default values could come to effect. But I need to updated the artifact name’s field which I just realized I didn’t. Next commit. If you switch to LIB_STATIC build type, the output folder and the output extension will change to lib.

Also, before I committed these changes I merged Bruno’s recent changes (mostly GDC related stuff).

The corresponding change set in the source code: r080d4e50bc25

IModelElement Icons

My previous experiments with DDT were about to change how the Outline View looks like in DDT. It was a good exercise to understand the Eclipse plug-in development basics and learn Bruno’s code. However, it didn’t work out as I expected as it took quite a while to understand how the DLTK assist the plug-in to build a model from the source code. This IModelElement hierarchy represents the basic model of the project’s tree and therefore this is to be used by any graphical representation as it is in the ScriptView or the OutlineView.

Later Bruno unified the whole stuff in the DeeModelElementLabelProvider which works in three different context: Script View (navigation), Outline View (view), and the Completion Proposal (CodeAssist). As I can’t settle with the current icons I decided to change this bit of the code. Bruno made it clear that he wants to use the private/public/protected modifiers as an overlay, but I rather would not use that in the case of fields and methods. The reason for this is simple: The overlayed icons have limited space, and a field (variable) or a method (function) could possible have quite a few modifiers such as “private static immutable” thus having three overlays would look like quite crowded.

As a result, I brought my previous patch in play, adding the JDT’s icons for methods and fields. At the moment I didn’t add other things, but it only needs a little painting to get a private/public/protected overlay for other elements, such as classes, structs, enums, interfaces, etc.

I couldn’t find my complete previous work however: Previously I added the types/return types to all these fields, similarly to JDT. Anyway, the stuff looks like this right now:

The corresponding change set in the source code: r427c36a3c2e4

Features that worth to look at

DDT is still quite immature so there are plenty of features missing to make it a productive development environment. Browsing in the code and messing with the product it self I decided to come up with an approximate list of features which should be implemented in order to make DDT worth to work with as a IDE for D development in the long run. The following list will change a lot in the future as I will revisit in the light of ongoing development.

Static and Dynamic library support: In a real software ecosystem static libraries are essential more than anything else. To add the static library support seems easy, but I haven’t tried any dynamic library with D yet.

Debugger support: This is perhaps the biggest one. There is no development IDE without a useful debugger interface and unfortunately DDT is lacking one. And also, this is quite a problem with D in it self. As far as my experiments went, the only compiler that produces some meaningful debug-info is DMD, but we have a limited support for command-line based debuggers. GDB would be a perfect choice, but at the moment I have no convincing evidence that the GDB’s D support is working to this moment. I need to investigate the matter further.

Refactoring: The CodeAssist for D is quite promising and I don’t see any issue to implement the most popular refactoring strategies: it’s just matter of time and arse.

Unit-testing IDE integration: It is imperative in the software development these days to offer a good, reliable testing facility for the developers. JUnit has an excellent support in Eclipse, where you can track in a graphical way what unit tests are present in the source code and we can have a good report on their progress in the test view.

As a frame work, I think it worth to have a look at the Felt project as it is aimed to provide all the agile goodies through several library. The DUnit framework in particular provides the unit testing framework which I could build a IDE support for. The real deal here is to parse the output of the unit test executable. Unfortunately it seems to rely on the Tango library which I find quite disturbing as the Tango is an optional library, but in this case all software that would use the Felt libraries, will depend on Tango. As the Felt library was updated quite a long time ago, as I try to explore it, I should remove the dependencies to the Tango library.

Quick Reminder How to Develop DDT

As I ran in to problems as I tried to set up my Eclipse environment in order to develop the DDT plugin, I decided to make a quick reminder how the installation should look like. My development environment is Eclipse Indigo (3.7.x) on Windows.

  1. Make sure that the Eclipse is up-to-date completely. (Help/Check for software updates)
  2. First I need to install the PDE, the plug-in development plug-in for Eclipse. This is easy, however there are always problems with the naming. So, open up Help/Install New Software dialog from the menu, and select the repository Indigo – http://download.eclipse.org/releases/indigo. Untick the Group items by category and search for the phrase: “Eclipse Plug-in Development Environment”. Install it.
  3. DLTK 3.0: This is the default version line for Eclipse Indigo, so we should find it also in the eclipse repository. Help/Install New Software dialog, http://download.eclipse.org/releases/indigo. Untick the Group items by category and search for the phrase: ” Dynamic Languages Toolkit – Core Frameworks”. Install it.
  4. Since the original Descent project exists on an SVN repository, I need to install the Subversive SVN Client for Eclipse. In the same dialog as before, I check for the phrase:   “Subversive SVN Team Provider (Incubation)” and go.

As I expected EGit became part of the Eclipse Indigo project thus no additional installation will be required. Yet.

I need to be careful of the import order of the related projects. What I need accordingly to Bruno’s tutorial is to import the descent.compiler project from SVN. In the Package Explorer’s context menu click on the Import and select the SVN/Project from SVN repository. Stick the http://svn.dsource.org/projects/descent URL to the repository address and select on the resource page the trunk/descent.compiler project. Ta-dam! Oh, wait… the first time when you want to import from SVN, the subversive team provider plug-in will find that you don’t have a connector so, there’s a need to install one. After several try, I found that the SVNKit 1.35 works just fine to use.

Now comes the real deal, the source code of the DDT. Luckily, it’s really simple: Again, in the Package Explorer’s context menu click on the Import, select Git and in the upcoming dialog, click on the Clone… button.  There it is: paste the URL: https://code.google.com/a/eclipselabs.org/p/ddt/ and select the all the branches (well, the branches themselves is a bit funny, because it still seems that I need to add a new remote in order to get the other branches, but heck, it didn’t kill anything). Note, that the clone isn’t my google clone address, I’ll add that later as an upstream clone while Bruno’s one gonna be the downstream update site.

At the remote naming, I chose to use the bruno-* (* = branch name) format, so it’s gonna be easier to sort them. After all these, the package explorer gets littered with projects.

Follow

Get every new post delivered to your Inbox.

Join 163 other followers