I recently started using Rubberduck in my project. I have a class module with a property, Item defined like this:
Public Property Get Item(ByVal Key As Variant) As IValidator
Attribute Item.VB_UserMemId = 0
If Validators.Exists(Key) Then Set Item = Validators(Key)
End Property
Per the usual VBE behavior, the VB6 Attribute Item.VB_UserMemId = 0, was present when the module was exported, but not visible in the IDE otherwise. When I installed Rubberduck, this attibute disappeared (not sure if this was Rubberduck was responsible or something else), but I figured I'd try out the @DefaultMember annotation as described here:
'@DefaultMember
Public Property Get Item(ByVal Key As Variant) As IValidator
If Validators.Exists(Key) Then Set Item = Validators(Key)
End Property
Rubberduck reports the following issues:
Annotation 'DefaultMember' is illegal in this context.
Model or member '' has a 'DefaultMember' annotation, but no corresponding attribute.
The VB6 attribute is still missing when I export and, trying 'synchronize attributes/annotations in module' appears to do nothing.
What am I missing here?
For the probable cause of the loss of the default attribute, ref #3505. In short, the way Rubberduck refactors code at the moment is to replace the entire content of the code pane. Unfortunately, this removea all member attributes. We still have to figure out how to both keep the attributes and the undo state.
The intended idea of the attribute annotation was that there is the inspection you are getting together with a quickfix that adds the attribute to the module. Unfortunately, that quickfix is broken, see #3166, and has been deactivated to prevent is from causing damage.
That is the single most annoying thing - it's a known issue, and it's related to Rubberduck needing to actually export the code modules in order to pick up the module & member attributes.
See, every module has 2 parse trees: one from the "code pane pass", with the tokens having the exact position they have in the VBE's code panes. The other parse tree is from the "attributes pass", with the tokens having whatever positions they have in the exported text file.
So all is nice & good, we process the parse trees and scope the attribute values from the attributes pass to the member declarations we've extracted out of the code pane pass, and built some kind of a "semantic model" and we're equipped to analyze, refactor, and rewrite the code.
Except there's a problem: the rewriters are working off the code pane pass' token streams - and they have to, otherwise we'd be writing invalid attributes into the VBE...
The problem was described last December, when I announced that I wouldn't be pursuing the fixing of the "synchronize attributes/annotations" quickfix feature; the "missing annotation/attribute" inspections have since been removed.
In other words, we're stuck: the VBIDE API has no way of writing to module/member attributes, and even with the upcoming changes that will remove the need to export the modules to pick up these attributes, we'll still only ever be able to read them... which means we'll be losing them whenever we do anything with the code in the code panes.
The essence of the problem is that the VBE "conveniently" hides critical code from us (the attributes), and until we implement our own code panes and optionally hide (not remove) the attributes in those, we'll keep losing the attributes in every module we run a rewriter against.
The only fix for this is for us to implement our own code panes and expose the true code to our users - and this makes the @DefaultMember & friends annotations (and the corresponding inspections and quickfix) completely moot. No small task, but we'll get to it.
The only work-around until that's done, is unfortunately to avoid using refactorings and inspection quick-fixes in modules that contain member attributes... which sucks.
Okay that makes some sense regarding the disappearing attribute. It doesn't explain the "illegal in this context" issue, but I guess I should just consider @DefaultMember to be completely broken at the moment?
Correct. When I wrote the December article I was 95% done fixing that illegal annotation logic, and then that impossible-to-fix last 5% hit me... I probably shouldn't have discarded everything I had...
IIRC the illegal annotation inspection had a tweak since then, possible that the false positive is fixed already.
We deem this annotation, which is our own invention, only valid if the attribute is set as well. In case the attribute is not set, the inspection warns you that the annotation is aout of sync with the attribute. (There also was an inspection the other way around, which has been deactivated.) If it worked, the quickfix, then would add the attribute.
Since the quickfix is broken, the annotation is not too useful now. You might still use it for documentation of the existence of an attribute and to warn you n case the attribute vanishes.
Thanks for the detailed description of the problem. I am still exploring Rubberduck, but so far I find it to be an extremely useful tool despite some rough edges.
Can you check whether still experience your problems?
Now that PR #4686 got merged, only member attributes on members that get renamed should get lost on a refactoring.
Moreover, with PR #4641 merged, you should be able to add the missing attribute corrsponding to the @DefaultMember annotation via the Add Attribute quickfix.
Most helpful comment
Thanks for the detailed description of the problem. I am still exploring Rubberduck, but so far I find it to be an extremely useful tool despite some rough edges.