Rubberduck 2.1.x

The release was going to include a number of important fixes for the missing annotation/attribute inspection and quick-fix, but instead we disabled it, along with a few other buggy inspections, and pushed the release – 7 months after 2.0.13, the last release was now over 1,300 commits behind, and we were reaching a point where we knew a “green release” was imminent, but also a point where we were going to have to make some more changes to parts of the core – notably in order to implement the fixes for these broken annotation/attribute inspections.

So we shipped what we had, because we wouldn’t jeopardize the 2.1 release with parser logic changes at that point.

Crossroads

wooden_signpost_at_the_crossroads1
By Hillebrand Steve, U.S. Fish and Wildlife Service [Public domain], via Wikimedia Commons
So here we are, at the crossroads: with v2.1.0 released, things are going to snowball – there’s a lot on our plates, but we now have a solid base to build upon. Here’s what’s coming:

  • Castle Windsor IoC: hopefully-zero user-facing changes, we’re replacing good old Ninject with a new dependency injection framework in order to gain finer control over object destruction – we will end up correctly unloading!

That’s actually priority one: the port is currently under review on GitHub, and pays a fair amount of long-standing technical debt, especially with everything involving menus.

  • Annotation/Attributes: fixing these inspection, and the quick-fix that synchronizes annotations with module attributes and vice-versa, will finally expose VB module and member attributes to VBA code panes, using Rubberduck’s annotation syntax.

For example,  adding '@Description("This procedure does XYZ") on top of a procedure will tell Rubberduck that you mean that procedure to have a VB_Description attribute; when Rubberduck parses that module after you synchronize, it will be able to use that description in the context status bar, or as tooltips in the Code Explorer.

This is considered a serious issue, because it affects pretty much every single inspection. Luckily there’s a [rather annoying and not exactly acceptable] work-around (apply the fix bottom-to-top in a module), but still.

But there’s a Greater Picture, too.

The 2.1.x Cycle

At the end of this development cycle, Rubberduck will:

  • Work in the VB6 IDE;
  • Have formalized the notion of an experimental feature;
  • Have a working Extract Method refactoring;
  • Make you never want to use the VBE’s Project References dialog ever again;
  • Compute and report various code metrics, including cyclomatic complexity and nesting levels, and others (and yes, line count too);
  • Maybe analyze a number of execution paths and implement some of the coolest code inspections we could think of;
  • Be ready to get really, really serious about a tear-tab AvalonEdit code pane.

If all you’re seeing is Rubberduck’s version check, the next version you’ll be notified about will be 2.1.2, for which we’re shooting for 2017-11-13. If you want to try every build until then (or just a few), then you’ll want to keep an eye on our releases page!

Up for Grabs

One of the best things about open-source software is that, when you find a bug as a user, you can not only report it to the developers, but also dig into the source code yourself and perhaps locate and fix the problem and PR it into the next release.

From the very beginning of our GitHub history, we’ve used issues as our “to-do” list, the “project backlog”. With GitHub projects we have subdivided the issue list into easier-to-track projects, as was shown last month. Thing is, with the few of us, the lots of you and the pretty wide project scope, the “to-do” list is constantly growing with awesome ideas.

There’s quite a lot to do in Rubberduck, and because we’d like you to help us do this, a lot of these things have an [up-for-grabslabel in our repository.

Some are easier than others. Of course it’s not always obvious to assess the “difficulty level” of an issue, but we can try:

difficulty-levels

Duckling (14 open) is labeling the “simple” issues we think don’t really require much experience with the code base. e.g. #1732 Inspection for empty modules

Ducky (17 open)  issues are more involved than duckling; if you haven’t been poking around too much, these ones might be more challenging. e.g. #2704 Concrete implementations should be private

Duck (13 open) issues are for contributors that would like something trickier and/or more substantative to tackle. e.g. #298 VB6 IDE Support

Quackhead (1 open) issues need contributors that know how Rubberduck understands VBA code and interacts with the VBE. e.g. #403 Static Analysis & Code Metrics

And then there’s all the others that we haven’t got around to stick an [up-for-grabs] label on, that you can just go and ask about anytime you like.


But… I don’t do C#!

Doesn’t matter! Our wiki needs to document all the refactorings and inspections; unit testing section could use articles about writing testable, object-oriented VBA code…

@Vogel612 made a translation helper (in Java!), to make it easier to localize Rubberduck and translate the resource files; if you can translate English into a language that’s not yet supported (we had to drop a few languages in 2.0, due to the sheer amount of new but untranslated resource strings), we’ll be happy to guide you and answer every question you might have about any of these resource strings.

But… I don’t do VBA!

Doesn’t matter! In fact, while VBA code is ultimately our data, there’s plenty of areas that don’t even need to get anywhere near actual VBA code. The regex builder tool for example, couldn’t care less about VBA (well aside from building VBScript-flavored regex…), and traversing an expression tree to evaluate/interpret it, determining if a conditional evaluates to a constant, …these things aren’t VBA-specific – they’re just things you need to work with, regardless of what language your data is written with. Except BrainFuck perhaps. Point is, knowing VBA helps, but the core team is there to help too if need be…

I mean, how much VBA do you need to know in order to be able determine whether a module is empty?

 

So, 2.0.12 is late… what’s cooking?

Recently I tweeted this:

The release of Rubberduck 2.0.12, due 5 days ago, is being delayed because we have something awesome cooking up. Give us 2-3 more weeks 🙂

TL;DR: if awesomeness can be cooked, that’s what’s cooking.

The amount of work that went into the upcoming release is tremendous. We’ve been trying to figure out exactly what was blowing up when the VBE dismantled itself and the host was shutting down, causing that pesky crash on exit… ever since we’ve introduced WPF user controls in dockable toolwindows. And at last, solved it.

We’ve been working on improving performance and thread safety of the entire parsing engine, and fixed a few grammar/parser bugs on the way, including a long-standing bug that made redundant parentheses trip a parse exception, another with the slightly weird and surely redundant Case Is = syntax, and @Magic annotations can now legally be followed by any comment, which is useful when you want to, well, annotate an annotation:

'@Ignore ProcedureNotUsed; called by [DoSomething] button on Sheet12
Public Sub DoSomething()
    ...
End Sub

We’ve enhanced the COM reference collector such that the resolver has every bit of useful information about everything there is to know in a type library referenced by a VBA project. This allows us to enhance other features, like the context-sensitive commandbar that tells you what Rubberduck is your selection as, e.g. a TextBox control in a UserForm:

textbox

(don’t mind that “Serialize” button – it’s only there in debug builds ;^)

Oh, and then there’s the interactions with the website – we’ll be running the inspections and the indenter on the website, and we’ll have the ability to (optionally) have Rubberduck know when a new version is available!


2.0.12 is going to be epic.

The 2.0 build

And then there’s even more: we’re going to make the inspections a concern of the parser engine, and turn them into parse tree node annotations – which means the code that currently finds the Declaration that’s currently selected (or one of its references), can also be used to find inspection results associated with that particular Declaration; this will probably prompt a redesign of how we present inspection results, and will definitely improve performance and memory footprint.

One of the best 2.x features is probably going to be the add/remove references dialog, which is currently merely prototyped. Beefing up unit testing with data-driven tests is also going to be a big one.

And when you see where we want to be for 3.0 (code path analysis & expression resolution, plug-in architecture, a subclassed CodePanethat actually tells us what’s going on, perhaps even with our own enhanced IntelliSense, more host-specific behaviors, TONS of new inspections), …this project is so awesome, I could just keep going on and on.

Not coming soon enough? I know, right!

cr-ducky-great-again-600x500.

To be continued…

 

Issues, Milestones and Projects

When the Rubberduck project was first put on GitHub, we quickly decided to use issues as our “todo list”. Right then, we knew we were going to need some label system. Since everything had started on a Stack Exchange site, labels were made to look like SE tags – and came to be used as such: our “categories” labels are all the same color: DDDDDD.

tags

“Oh wow, that must be so boring!”, right?

A little bit, indeed. So we made the status tags red (B60205), the meta-tags almost-white (FEFEFE), subcategories dark gray (808080); then we have [support] in blue (0077AA), [up-for-grabs] in forest green (0E8A16) and [help-wanted] in bright gold (FBCA04), to catch the eye easily.

So we went on a spree and created an issue for every feature we (then) could think of, and Rubberduck was officially kicked off as a long-term project, and I felt like we were managing it ok.

Especially since we started creating milestones and assigning one to issues. One mistake you don’t want to make, is to create a Next Release milestone – before you know it it’s impossible to know what was fixed when!

So a milestone was created for the “initial release”, then for “version 1.1”. Then I created one dedicated to get parsing powered by ANTLR – milestones were no longer release dates, but now little projects within the project, being worked on as reported and discovered bugs were assigned under the release milestone.

It worked that way until.. very recently. Looking back, I’d say what didn’t work was that our releases were revisions but our milestones were minor releases – so there was an undetermined number of releases under one given milestone. “v2.0.12” is the first milestone in the repository that’s actually numbered after a revision – and against which there will be only one release.

So, to recap:

  • Issues ideally describe one bug or feature request
  • Milestones ideally regroup all issues to be closed for a given release

Starting with 2.0.11/12, we’re going to be shooting for monthly releases, so a new milestone should be created every month or so: Rubberduck releases have been pretty random up to this point, and with a release-per-milestone it’s going to be much easier to plan and track the “current sprint”.

Or will it? Something is missing.

Projects

That’s what the “little projects within the project” milestones should have been from the beginning: a project. On GitHub a project lets you create columns to move cards to/from, and if you add an issue as a card to your “In Progress” column, the issue page will say “In Progress in [Project]” in the side bar.. which is pretty cool!

board.PNG

As of yesterday, Rubberduck has two types of projects:

Things we plan and track for [every] next release

There’s two of them:

  • Features tracks feature requests and enhancements to existing features.
  • BugSlayer tracks all reported bugs.

These projects have columns that help plan work, and visualize everything much more easily than with the issues list:

  • Requested / Reported
  • Deferred / Hold
  • Planned
  • Planned for next release
  • Assigned / In Progress
  • Merged
  • Released

Things we plan and track for some eventual release

When an important feature requires more work than can reasonably be tracked with a single issue / card in the Features project, a project board dedicated to that feature can be created to make it easier to track work and facilitate collaboration.

These projects have a “classical” set of columns:

  • TODO
  • In Progress
  • Done

Do you need all that for a small side-project? Maybe not… but I don’t see how it can hurt. Rubberduck isn’t really a small project anymore, though, but it’s still built by a handful of people that find a few spare hours to devote regularly. With the number of open issues (over 300), tracking things in the issues list was starting to feel like tracking help desk tickets with Outlook email follow-up flags – GitHub projects change everything. Heck, I think they’re making me start liking project management!

IDE-Integrated Git Source Control

It was merged just yesterday. When Rubberduck 2.0 is released, VBA devs will have a new tool in their arsenal: full-fledged Git source control, seamlessly integrated into their IDE, in a dockable toolwindow:

sc-panel.PNG

Why use Source Control?

How many of you keep version and change tracking information in comments? Does this look any familiar?


'modified 2014-04-27, ticket #173

Or this perhaps?

'version 1.2
' - added CalculateRangePrices macro
' - fixed bug in SalesByCustomerReport

These things don’t belong in code, they belong in your commit history. Using source control gives you that, so you can have code files that contain, well, code.

Collaborative work in VBA is pretty annoying anyway – you have to manually merge changes, and import/export modules manually, if you’re not outright copy/pasting code. This is error-prone and, let’s face it, nobody does it.

With Rubberduck and your GitHub repository two clicks away, you can now work on your code even if you don’t have the macro-enabled workbook with you right now. Because Rubberduck doesn’t just dump the .xlsm file into a GitHub repo – it actually exports each individual code file (yes, including workbooks and worksheets and UserForms) into an actual working directory, so you can work in VBA just like you would in VB6.. or C#, or Java.

You can create a branch, and work on a feature while shielding your “master” branch from these changes, issue a bug-fix on “master”, merge the bug-fix into your dev branch, finalize your work, then merge your dev branch into master, and release a new version: that’s how devs work, and that’s how VBA devs can work too, even if they’re a lone wolf.

Source Control integration was issue #50 in Rubberduck’s repository (we’re now at #1219, some 3,000 commits later) – we wanted this feature all along. And we’re delivering it next release, promise.

Special thanks to @Hosch250, who worked astonishingly hard to make this happen.

See how it works on our wiki (yes, that’s work in progress).

 

Breaking Changes – Part 1: Parser

Rubberduck 2.0 flips everything around.

When numbering versions, incrementing the “major” digit is reserved for breaking changes – and that’s exactly what Rubberduck 2.0 will introduce.

I have these changes in my own personal fork at the moment, not yet PR’d into the main repository.. but as more and more people fork the main repo I feel a need to go over some of the changes that are about to happen to the code base.

If you’re wondering, it’s becoming clearer now, that Rubberduck 2.0 will not be released until another couple of months – at this rate we’re looking at something like the end of winter 2016… but it’s going to be worth the wait.


 

Parser State

Parsing in Rubberduck 1.x was relatively simple:

  • User clicks on a command that requires a fresh parse tree;
  • Parser knows which modules have been modified since the last parse, so only the modified modules are processed by the ANTLR parser;
  • Once we have a parse tree and a set of Declaration objects for everything (modules, procedures, variables, etc.), we resolve the identifier usages we encounter as we walk the parse tree again, to one of these declarations;
  • Once identifier resolution is completed, the command can run.

The parse results were cached, so that if the Code Explorer processed the entire code base to show up, and then the user wanted to run code inspections or one of the refactor commands, they could be reused as long as none of the modules were modified.

Parsing in Rubberduck 2.0 flips this around and completely centralizes the parser state, which means the commands that require a fresh parse tree can be disabled until a fresh parse tree is available.

We’ve implemented a key hook that tells the parser whenever the user has pressed a key that’s changed the content of the active code pane. When the 2.0 parser receives this message, it cancels the parse task (wherever it’s at) for that module, and starts it over; anytime there’s a “ready” parse tree for all modules, the expensive identifier resolution step begins in the background – and once that step completes, the parser sends a message to whoever is listening, essentially saying “If you ever need to analyze some code, I have everything you need right here”.

Sounds great! So… What does it mean?

It means the Code Explorer and Find Symbol features no longer need to trigger a parse, and no longer need to even wait for identifier resolution to complete before they can do their thing.

It means no feature ever needs to trigger a parse anymore, and Rubberduck will be able to disable the relevant menu commands until parser state is ready to handle what you want to do, like refactor/rename, find all references or go to implementation.

It means despite the VBE not having a status bar, we can (read: will) use a command bar to display the current parser state in real-time (as you type!), and let you click that parser state command button to expand the parser/resolver progress and see exactly what little ducky’s working on in the background.


To be continued…

There’s a new duck in town!

…and it rocks.

The past few months have been tough. We were facing some serious ANTLR grammar bugs, and our identifier resolver had even more serious bugs, which meant false positives in code inspections, a rename refactoring that wouldn’t always rename all references, and a StackOverflowException if you were unlucky… which blew up Rubberduck, the VBE, and the Office host app with it, without warning.

That’s why 1.3 remained a “pre-release”.

Rubberduck 1.4 has none of these issues. Oh, our ANTLR grammar is still far from perfect (line numbers, and “precompiler” #IF statements come to mind) – but a number of bugs were fixed, and the resolver was completely rewritten. It’s not as perfect as we’d like it to be, but it correctly resolved everything we threw at it, without a single exception.

So, what’s so cool about it?


 

#Refactor

Extract Method has been around since version 1.2, and Rename was pre-released (albeit with some issues) with 1.3; Rubberduck 1.4 introduces two new refactorings:

  • Reorder Parameters in a procedure, and automatically adjust all call sites.
  • Remove Parameters from a procedure’s signature, and automatically adjust all call sites.

Rename can be used from the Project Explorer, Code Pane or Form Designer context menus, as well as from the Code Explorer to rename a project, a component (form, module, class), a procedure, variable, line label, …anything. This completely eliminates all excuses to keep meaningless identifiers in your code.


 

#Navigate

The Code Explorer was already a nice feature in 1.2, but Rubberduck 1.4 takes navigation to a whole new level.

  • Find Symbol lets you search for anything – and go to its declaration.
  • Find all references displays all call sites of any identifier.
  • Go to implementation lets you navigate implementations of an interface or interface members. Rubberduck considers any class referenced by an Implements statement as an interface.

One cool thing is that we’ve created declarations for pretty much everything in the Standard VBA library, so you can use find all references to list all usages of, say, MsgBox, or Err.Raise.


#Git

That’s right. We’ve talked about it for a while. Well, it’s here. Integrated source control, right there in the VBE. Commit, push, pull, merge, branch, to and from local or remote repositories on GitHub.


And so much more…

If you’ve never used a previous version of Rubberduck, now is the time.

Every VBA programmer needs a Rubberduck.

DOWNLOAD