rubberduck-vba / Rubberduck

Every programmer needs a rubberduck. COM add-in for the VBA & VB6 IDE (VBE).
https://rubberduckvba.com
GNU General Public License v3.0
1.9k stars 299 forks source link

Inspection for object variable reference that is subsequently only used as a With Block variable #3548

Open ThunderFrame opened 6 years ago

ThunderFrame commented 6 years ago

Given code like this, where a variable is declared and instantiated, but then never used beyond the with block.

'Late-bound variable declaration and creation
Dim oRegEx As Object
Set oRegEx = CreateObject("vbscript.regexp")
With oRegEx
   '....
End With

The code could be more concisely written as:

'Late-bound reference only:
'No variable declaration required, the variable only survives as long as the With Block
With CreateObject("vbscript.regexp")
    '....
End With

Or better still, prompt the user to make the reference early-bound

'Add a reference to Microsoft VBScript Regular Expressions 5.5
With New RegExp
    '....
End With

But the object needn't be a created object, it could just be using the host's model:

Dim doc As Document
Set doc = ThisDocument
With ThisDocument
    '....
End With

'Would become....
With ThisDocument
    '....
End With
retailcoder commented 6 years ago

Doesn't need much code path analysis: we just need to know that there's only a single reference that isn't an assignment, and the parent of that reference's context is a With block. Covers the first case anyway; the last case would already pop a 'variable assigned but not referred to' inspection result; I think early/late binding is beyond the scope of that inspection though.

bclothier commented 6 years ago

Note that a potential issue is that typing may get lost. We probably don't want that. Example:

Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone 'This returns an object, cast to DAO.Recordset
With rs
  ...
End With

The inspection should not fire for those, IMO.

ThunderFrame commented 6 years ago

@bclothier, good point. Same would apply to:

With ThisWorkbook.Worksheets("Foo")
    '....
End With