Static code analysis can find hundreds of opportunities in VBA code.
Rubberduck builds its own internal representation of the code, and then proceeds to analyze it. Each individual inspection can easily be disabled, or configured to issue inspection results at different severity levels ranging from Hint
to Error
.
Use the Inspection Results toolwindow to review Rubberduck’s findings, search, filter, regroup results by inspection, location, type, or severity. Each inspection result comes with a detailed description of what’s being flagged and why, so you can make an enlightened decision.
Unless configured otherwise, Rubberduck automatically runs inspections after the a parser/resolver cycle completes (regardless of whether the inspection results toolwindow is displayed or not).
For the best experience, it would be recommended to first try Rubberduck with an empty project, add a new module, and write, say, a loop that counts 1 to 10 and outputs to the debug pane - then to parse that and review the inspection results; carefully review the inspection settings, and consider disabling the inspections that irreconcilably clash with your preferences: use meaningful names alone can easily produce hundreds upon hundreds of results if you’re not that much into using vowels, or if you, say, prefix all your variable names; these inspections can be re-enabled anytime you’re ready!
This tab lists all items found in the .xml documentation assets from the latest pre-release build. To modify this content, a pull request must be merged into the [next] branch.
Identifies line labels that are never referenced, and therefore superfluous.
Default severity: Warning
Line labels are useful for GoTo, GoSub, Resume, and On Error statements; but the intent of a line label can be confusing if it isn't referenced by any such instruction.
Warns about member calls against an extensible interface, that cannot be validated at compile-time.
Default severity: Warning
Extensible COM types can have members attached at run-time; VBA cannot bind these member calls at compile-time. If there is an early-bound alternative way to achieve the same result, it should be preferred.
Flags the value-parameter of a property mutators that are declared with an explict ByRef modifier.
Default severity: Warning
Regardless of the presence or absence of an explicit ByRef or ByVal modifier, the value-parameter of a property mutator is always treated as though it had an explicit ByVal modifier. Exception: UserDefinedType and Array parameters are always passed by reference.
Warns about a malformed Rubberduck annotation that is missing one or more arguments.
Default severity: Error
Some annotations require arguments; if the required number of arguments isn't specified, the annotation is nothing more than an obscure comment.
Indicates that a Rubberduck annotation is documenting the presence of a VB attribute that is actually missing.
Default severity: Warning
Rubberduck annotations mean to document the presence of hidden VB attributes; this inspection flags annotations that do not have a corresponding VB attribute.
Indicates that a hidden VB attribute is present for a member, but no Rubberduck annotation is documenting it.
Default severity: Warning
Rubberduck annotations mean to document the presence of hidden VB attributes; this inspection flags members that do not have a Rubberduck annotation corresponding to the hidden VB attribute.
Indicates that a hidden VB attribute is present for a module, but no Rubberduck annotation is documenting it.
Default severity: Warning
Rubberduck annotations mean to document the presence of hidden VB attributes; this inspection flags modules that do not have a Rubberduck annotation corresponding to the hidden VB attribute.
Warns about module-level declarations made using the 'Dim' keyword.
Default severity: Suggestion
Private module variables should be declared using the 'Private' keyword. While 'Dim' is also legal, it should preferably be restricted to declarations of procedure-scoped local variables, for consistency, since public module variables are declared with the 'Public' keyword.
Indicates that a user module is missing a @Folder Rubberduck annotation.
Default severity: Suggestion
Modules without a custom @Folder annotation will be grouped under the default folder in the Code Explorer toolwindow. By specifying a custom @Folder annotation, modules can be organized by functionality rather than simply listed.
Locates module-level fields that can be moved to a smaller scope.
Default severity: Hint
Module-level variables that are only used in a single procedure can often be declared in that procedure's scope. Declaring variables closer to where they are used generally makes the code easier to follow.
Flags parameters declared across multiple physical lines of code.
Default severity: Suggestion
When splitting a long list of parameters across multiple lines, care should be taken to avoid splitting a parameter declaration in two.
Flags declaration statements spanning multiple physical lines of code.
Default severity: Warning
Declaration statements should generally declare a single variable.
Warns about 'Function' and 'Property Get' procedures whose return value is not assigned.
Default severity: Error
Both 'Function' and 'Property Get' accessors should always return something. Omitting the return assignment is likely a bug.
Warns about assignments that appear to be assigning an object reference without the 'Set' keyword.
Default severity: Error
Omitting the 'Set' keyword will Let-coerce the right-hand side (RHS) of the assignment expression. If the RHS is an object variable, then the assignment is implicitly assigning to that object's default member, which may raise run-time error 91 at run-time.
Identifies places in which an object is used but a procedure is required and a default member exists on the object.
Default severity: Warning
Providing an object where a procedure is required leads to an implicit call to the object's default member. This behavior is not obvious, and most likely unintended.
Warns about 'Declare' statements that are using the obsolete/unsupported 'CDecl' calling convention on Windows.
Default severity: Warning
The CDecl calling convention is only implemented in VBA for Mac; if Rubberduck can see it (Rubberduck only runs on Windows), then the declaration is using an unsupported (no-op) calling convention on Windows.
Locates explicit 'Call' statements.
Default severity: Suggestion
The 'Call' keyword is obsolete and redundant, since call statements are legal and generally more consistent without it.
Locates legacy 'Rem' comments.
Default severity: Suggestion
Modern VB comments use a single quote character (') to denote the beginning of a comment: the legacy 'Rem' syntax is obsolete.
Locates legacy 'Error' statements.
Default severity: Suggestion
The legacy syntax is obsolete; prefer 'Err.Raise' instead.
Locates legacy 'Global' declaration statements.
Default severity: Suggestion
The legacy syntax is obsolete; use the 'Public' keyword instead.
Locates explicit 'Let' assignments.
Default severity: Suggestion
The legacy syntax is obsolete/redundant; prefer implicit Let-coercion instead.
Flags usages of members marked as obsolete with an @Obsolete("justification") Rubberduck annotation.
Default severity: Warning
Marking members as obsolete can help refactoring a legacy code base. This inspection is a tool that makes it easy to locate obsolete member calls.
Flags declarations where a type hint is used in place of an 'As' clause.
Default severity: Suggestion
Type hints were made obsolete when declaration syntax introduced the 'As' keyword. Prefer explicit type names over type hint symbols.
Flags 'While...Wend' loops as obsolete.
Default severity: Warning
'While...Wend' loops were made obsolete when 'Do While...Loop' statements were introduced. 'While...Wend' loops cannot be exited early without a GoTo jump; 'Do...Loop' statements can be conditionally exited with 'Exit Do'.
Flags obsolete 'On Local Error' statements.
Default severity: Suggestion
All errors are "local" - the keyword is redundant/confusing and should be removed.
Flags modules that specify Option Base 1.
Default severity: Hint
Implicit array lower bound is 0 by default, and Option Base 1 makes it 1. While compelling in a 1-based environment like the Excel object model, having an implicit lower bound of 1 for implicitly-sized user arrays does not change the fact that arrays are always better off with explicit boundaries. Because 0 is always the lower array bound in many other programming languages, this option may trip a reader/maintainer with a different background.
Flags modules that omit Option Explicit.
Default severity: Error
This option makes variable declarations mandatory. Without it, a typo gets compiled as a new on-the-spot Variant/Empty variable with a new name. Omitting this option amounts to refusing the little help the VBE can provide with compile-time validation.
Flags parameters that are passed by reference (ByRef), but could be passed by value (ByVal).
Default severity: Suggestion
Explicitly specifying a ByVal modifier on a parameter makes the intent explicit: this parameter is not meant to be assigned. In contrast, a parameter that is passed by reference (implicitly, or explicitly ByRef) makes it ambiguous from the calling code's standpoint, whether the procedure might re-assign these ByRef values and introduce a bug.
Identifies parameter declarations that are not used.
Default severity: Warning
Declarations that are not used anywhere should probably be removed.
Warns about 'Sub' procedures that could be refactored into a 'Function'.
Default severity: Suggestion
Idiomatic VB code uses 'Function' procedures to return a single value. If the procedure isn't side-effecting, consider writing is as a 'Function' rather than a 'Sub' the returns a result through a 'ByRef' parameter.
Locates procedures that are never invoked from user code.
Default severity: Warning
Unused procedures are dead code that should probably be removed. Note, a procedure may be effectively "not used" in code, but attached to some Shape object in the host document: in such cases the inspection result should be ignored.
Locates places in which a procedure needs to be called but an object variables has been provided that does not have a suitable default member.
Default severity: Warning
The VBA compiler does not check whether the necessary default member is present. Instead there is a runtime error whenever the runtime type fails to have the default member.
Flags MSForms controls being accessed from outside the UserForm that contains them.
Default severity: Hint
MSForms exposes UserForm controls as public fields; accessing these fields outside the UserForm class breaks encapsulation and couples the application logic with specific form controls rather than the data they hold. For a more object-oriented approach and code that can be unit-tested, consider encapsulating the desired values into their own 'model' class, making event handlers in the form manipulate these 'model' properties, then have the code that displayed the form query this encapsulated state as needed.
Identifies Property assigment references where Set or Let Property Members do not exist.
Default severity: Warning
In general, the VBE editor catches this type of error and will not compile. However, there are a few scenarios where the error is overlooked by the compiler and an error is generated at runtime. To avoid the runtime error scenarios, the inspection flags all assignment references of a read-only property.
Identifies redundant ByRef modifiers.
Default severity: DoNotShow
This inspection will not run by default, it must be manually enabled in Code Inspections configuration settings.
Out of convention or preference, explicit ByRef modifiers could be considered redundant since they are the implicit default. This inspection can ensure the consistency of the convention.
Identifies redundant module options that are set to their implicit default.
Default severity: Hint
Module options that are redundant can be safely removed. Disable this inspection if your convention is to explicitly specify them; a future inspection may be used to enforce consistently explicit module options.
Identifies auto-assigned object declarations.
Default severity: Suggestion
Auto-assigned objects are automatically re-created as soon as they are referenced. It is therefore impossible to set one such reference to 'Nothing' and then verifying whether the object 'Is Nothing': it will never be. This behavior is potentially confusing and bug-prone.
Locates assignments to object variables for which the RHS does not have a compatible declared type.
Default severity: Warning
The VBA compiler does not check whether different object types are compatible. Instead there is a runtime error whenever the types are incompatible.
Identifies identifiers that hide/"shadow" other identifiers otherwise accessible in that scope.
Default severity: DoNotShow
This inspection will not run by default, it must be manually enabled in Code Inspections configuration settings.
Global namespace contains a number of perfectly legal identifier names that user code can use. But using these names in user code effectively "hides" the global ones. In general, avoid shadowing global-scope identifiers if possible.
Locates ThisWorkbook.Worksheets and ThisWorkbook.Sheets calls that appear to be dereferencing a worksheet that is already accessible at compile-time with a global-scope identifier.
Default severity: Suggestion
Sheet names can be changed by the user, as can a worksheet's index in ThisWorkbook.Worksheets. Worksheets that exist in ThisWorkbook at compile-time are more reliably programmatically accessed using their CodeName, which cannot be altered by the user without accessing the VBE and altering the VBA project.
This inspection will only run if the Excel library is referenced.
Locates 'For' loops where the 'Step' token is omitted.
Default severity: DoNotShow
This inspection will not run by default, it must be manually enabled in Code Inspections configuration settings.
Out of convention or preference, explicit 'Step' specifiers could be considered mandatory; this inspection can ensure the consistency of the convention.
Locates 'For' loops where the 'Step' token is specified with the default increment value (1).
Default severity: Hint
Out of convention or preference, explicit 'Step 1' specifiers could be considered redundant; this inspection can ensure the consistency of the convention.
Locates 'Stop' instructions in user code.
Default severity: Suggestion
While a great debugging tool, 'Stop' instructions should not be reachable in production code; this inspection makes it easy to locate them all.
Warns about Rubberduck annotations with more arguments than allowed.
Default severity: Warning
Most annotations only process a limited number of arguments; superfluous arguments are ignored.
Identifies assignments without Set for which both sides are objects.
Default severity: Warning
Whenever both sides of an assignment without Set are objects, there is an assignment from the default member of the RHS to the one on the LHS. Although this might be intentional, in many situations it will just mask an erroneously forgotten Set.
This inspection warns about references to the default instance of a class, inside that class.
Default severity: Warning
While a stateful default instance might be intentional, when it isn't it's easily a source of bugs. Use the Me qualifier to explicitly refer to the current instance and eliminate any ambiguity. Global state accidentally stored in a class' default instance is not shared by all other instances of that class.
Warns when a variable is referenced prior to being assigned.
Default severity: Error
An uninitialized variable is being read, but since it's never assigned, the only value ever read would be the data type's default initial value. Reading a variable that was never written to in any code path (especially if Option Explicit isn't specified), is likely to be a bug.
Warns about implicit local variables that are used but never declared.
Default severity: Error
If this code compiles, then Option Explicit is omitted and compile-time validation is easily forfeited, even accidentally (e.g. typos).
Warns about public class members with an underscore in their names.
Default severity: Warning
The public interface of any class module can be implemented by any other class module; if the public interface contains names with underscores, other classes cannot implement it - the code will not compile. Avoid underscores; prefer PascalCase names.
Finds instances of 'On Error Resume Next' that don't have a corresponding 'On Error GoTo 0' to restore error handling.
Default severity: Warning
'On Error Resume Next' should be constrained to a limited number of instructions, otherwise it supresses error handling for the rest of the procedure; 'On Error GoTo 0' reinstates error handling. This inspection helps treating 'Resume Next' and 'GoTo 0' as a code block (similar to 'With...End With'), essentially.