Open bclothier opened 5 years ago
Addendum: the userforms also have the same behavior so it is obvious that there is a feature that enables the container to support member access via dot operator to the collection members. For the refactoring to be most productive, we'll need to be able to recognize when the container (be it Access Form/Report or Userform) can make dotted access and refactor toward that over the collection unlike the case of recordsets.
Wouldn't that just be the default member? UserForm.Controls
and Recordset.Fields
aren't all that different.
Both are default members, yes but last time I checked rs.SomeField
is a compile error whereas frm.SomeControl
isn't. In the latter case, it's obviously doing some extra to enable the dot access on the member (e.g. adding the controls to the interface dynamically). Recordsets never exhibit that behavior. In the cases of forms/reports/userforms, I suspect that being persisted, they can dynamically update the interface and thus expose the members directly on the interface, whereas recordsets and other similar objects can't since they are always created at the runtime -- there is no way of knowing what shape they'll have until then and it's already too late.
Just for references, two things to investigate that may or may not be relevant to this:
defaultcollelem attribute which is labeled as "Visual Basic optimization. Not sure if the interfaces get decorated this way, which would then enable the dot access?
IVBGetControl::EnumControls method If the object implements this interface that might be also what enables the dot access?
A counterexample --
Dim c As ADODB.Connection
Set c = New ADODB.Connection
c.foo
This compiles (but yield a runtime error unless I actually connect to some source that has foo
as a procedure or something. However, unlike the frm.SomeControl
case, there is no intellisense downstream from the foo
. Note that by default, all COM interfaces are extensible -- to disallow dot access on random members, the interface must use the nonextensible
attribute, which is the case with DAO.Recordset
& ADODB.Recordset
and thus why it will yield a compile error, but not on ADODB.Connection
.
Sorry, I linked the wrong issue in the PR closing this. The part about controls is still open.
Justification When replying to #5092 I thought we already had a request for this refactoring but was surprised that there wasn't.
The proposal is to have a simple refactor that converts all bang operators into dot operators -- there is no legit reason to use bang operators, especially on
Me
on the LHS. The refactor should expand the expressions (e.g. Access' form'sMe!Foo
should becomeMe.Foo
which is more descriptive of what the code is actually doing and more importantly makes the code verifiable.An unverifiable code is unrefactorable code. Rubberduck should help them write verifiable code.
Description Given:
Assuming an Access form and a DAO Recordset:
The outcome should be:
Note that the Access form can have dot access to the controls without going through the
Me.Controls
collection, but we can't do that for the recordset. That may require some inspection on the object to determine whether we can dot access the member or use the default collection.