- VB Classic
- Microsoft Visual Basic versions 3.0, 4.0, 5.0 and 6.0.
- Microsoft Visual Basic .NET, version 2002 onward.
- Office VBA
- Visual Basic for Applications in Microsoft Office.
- Sub, Function, Property, Declare Sub/Function, Operator, Event declaration.
- Each Property accessor (Get, Set and Let) is an individual procedure.
- Each Custom Event accessor (AddHandler, RemoveHandler and RaiseEvent) is an individual procedure.
- Anonymous lambda Subs and Functions do not count as procedures.
- Object variable
- A variable that can hold an object. The object can be, for example, a Class, a Form or a Control. Variants (VB 3-6) and Objects (VB.NET) are special cases because can hold both objects and other values.
- Late binding
- A call is late-bound if it cannot be resolved at compilation time. The destination of the call is only know at run-time. More about analysis of late-bound references
Dead code terminology
See also: Complete list of dead code rules.
- Dead/live code status table
|Live||In use. Keep.|
|Dead||Not in use. Remove.|
|Dead but exposed||Unknown. Can possibly remove.|
- Dead code
- Dead code means unnecessary, inoperative code that can be removed.
Being dead means that the element is not used and you can remove it without affecting the functionality of the program.
- Semi-dead code
- Semi-dead code is required at compile-time, but not when the program runs. Alternatively, semi-dead code is code that is in partial (improper) use. It often indicates a logic flaw somewhere in the code. More
- Live code
- Live code is the opposite of dead code. It is the code you need. All code is live until proven dead. If Project Analyzer cannot deduct that a programming element is 100% dead, it will mark it as live code to prevent accidental deletion of useful code.
- Dead procedure
- A dead procedure is not executed at run-time. Two main cases exist:
- A truly dead procedure is not called anywhere in the program. Such a procedure is not required for the code to compile or run. It can be removed.
- A procedure may be called by some other procedures, but all the callers are dead.
This kind of procedure is called Unexecuted or Callers all dead. It is required to compile but not to run the project. It can be removed when all the callers are removed too.
- Live procedure
- A procedure that's not dead.
The following kinds of procedures are also considered to be live procedures.
- Many event handlers. If we cannot determine whether an event actually fires or not, we assume that the event handlers are live. This rule affects regular event handlers of VB forms and controls. When your own classes declare Events and use RaiseEvents to fire them, we can analyze the deadness of the event handlers normally. Thus, handlers of events of your own classes can be reported as dead code.
- Procedures that implement an interface in classes using the Implements statement. When a class implements an interface, it's hard to detect if a call to an interface member is actually passed to the implementation. Often there are several implementations of a single interface, and picking the right implementation is only done at run-time. — In VB 5-6, an implementing procedure is named like BaseClass_Method. In VB.NET, it's declared using the Implements keyword.
— The deadness of procedures that are part of an Interface or an abstract base class is analyzed normally.
- Exposed procedures, which can be called from other projects. In certain project types, such as libraries, Public procedures in Public classes are visible outside the project. These procedures are called exposed procedures. Dead code reporting for exposed procedures depends on the current problem filter settings. By default, exposed procedures are considered to be alive. You can elect to consider them dead. See Exposed code terminology below.
- UserControl Public Properties (VB Classic). These are live because they can always be reached via VB's Properties window.
- Procedures declared Overrides, parent class unknown. In VB.NET, an Overrides procedure in a child class may execute in response to a call made on the parent class. If the parent class is unknown to the analysis, the call will not be analyzed. To suppress an extra dead code warning, we assume Overrides are live if the parent class is unknown.
- Default member procedures. These are left live because the reference to an object's default member is sometimes impossible to detect.
- Some other special cases exist where a procedure may be called in an invisible way and is thus live.
- Procedures marked as live code by a comment directive such as '$ PROBHIDE DEAD.
- Dead variable
- A variable is dead if it is not read or written to. Variables can also be semi-dead: written only, read only and no value given, see below.
- Dead field
- A field in a user-defined type is dead if it is not read or written to. Could also be semi-dead.
- Dead constant
- A constant whose value is not used in the code.
- Dead compiler constant
- A compiler constant (conditional compilation argument) whose value is not used for conditional compilation.
- Dead Enum constant
- A single enumeration constant whose value is not used in the code.
- Dead Enum
- An enumeration that is not used in the code at all.
Exposed code terminology
- A piece of code is exposed when it can be called from other projects. A typical case is DLL with a Public class with some Public methods in it. Starting with VB2005, even standard EXE projects can expose an interface. The following table summarizes which projects can expose an interface.
|Standard EXE||No (VB 3-6, VB 2002-2003)|
Yes (VB 2005-)
Being exposed is subject to the project type and scope declarations. In classic VB, the Instancing property of a class defines its scope. In VB.NET, the keywords Private, Protected, Friend and Public are used to control the scope. The below table shows which scopes can be exposed.
|Friend||No (VB 3-6, VB 2002-2005)|
No (VB2008- default)
Yes or no (VB2008- with <InternalsVisibleTo>)
No (in a NotInheritable Class)
|Protected Friend||Yes if either Friend or Protected is exposed.|
No if not.
The <InternalsVisibleTo> attribute, added to VB2008, allows external projects to call Friend members, even when Friend is normally limited to in-project use only. If <InternalsVisibleTo> is found, Project Analyzer treats Friend as exposed code when the external projects are not analyzed (and calls are unknown). If <InternalsVisibleTo> is found and all the referenced projects are analyzed, Project Analyzer treats Friend as not exposed (all calls are known).
In addition, a VBA procedure may be exposed to the host application or other documents.
- Dead but exposed
- This is code is status unknown, sort of. A piece of code was found to be unused, but it's also exposed to other projects. It's impossible to decide if the code is actually dead or not without analyzing all of the possible projects that may use it.
Your is dead but exposed. What should you do about it?
- Use Project Analyzer Enterprise Edition to analyze all possible caller projects together with this system. If "dead but exposed" still appears, it is truly dead code and you can remove it.
- With Project Analyzer Standard or Pro Edition, use your own knowledge of the system to determine whether "dead but exposed" code is in use or not.
- Alternatively, leave all "dead but exposed" code "as is" to avoid any compatibility problems with callers.
- If "dead but exposed" appears in a standard executable project (VB2005 or later) and the .exe file is not supposed to be referenced by external projects, you can consider the code to be truly dead and remove it.
By default, Project Analyzer hides dead code problems for exposed code. You can enable them in Problem options. Use this option in a multi-project analysis.
- May execute by external call
- This case is similar to "dead but exposed". A procedure has not been found to execute by calls within the analyzed code. However, it may execute as a response to a call from external program.
This happens if a procedure higher above in the call tree is exposed. A call to that procedure may lead to this procedure being executed.
Semi-dead code terminology
- Unexecuted - Callers all dead
- (Called by dead only)
- There are calls to a procedure, but all the callers are dead code. The code never executes.
- Event handled but not raised
- An event does not fire due to missing RaiseEvent.
- Implemented but not used
- An interface is implemented by one or more classes, but the interface is not used in any other way. The interface is useless.
- Not implemented
- An interface is used as a data type, but no classes implement the interface. A run-time error awaits the user.
- Not instantiated
- A class is used as a data type, but it is not instantiated anywhere. A run-time error awaits the user.
- Not inherited
- An abstract MustInherit base class is not inherited, even though it is used as a data type. Instances of the class cannot exist.
- Written, not read
- A variable or a type field is written to, but not read.
- Read, not written
- A variable or a type field is read, but not written to.
- No value given
- A variable or a type field is both read and written. However, no "real" data is written in it. The data is simply set to Nothing. Alternatively, an array is allocated, but no data is stored in it.
- Users all dead
- The code is referenced, but it is not in actual run-time use. The code is required for compilation only. You can delete this code along with the users.
- Readers all dead
- Variable read instructions exist, but none of the readers actually executes at run-time.
- Writers all dead
- Variable write instructions exist, but none of the writers actually executes at run-time.
Scopes and modules
- A programming element that is available throughout the entire project. Not equal to the obsolete Global keyword. Example: a Public variable in a standard module is global, while a Public variable in a class is module-level.
- A programming element that is not global or local. Anything declared outside procedures but not globally available.
- A programming element that is available in one procedure only. Procedure parameters and variables & constants declared within a procedure are local.
- Depending on the context, a module may refer to a standard module (.bas file or Module statement), any code file (including forms, classes and standard modules) or even a .NET Namespace, Interface, Structure or Class.
- Standard module
- VB 3-6: A .bas file.
VB.NET: code inside a Module statement.
- Class module
- In the strictest sense, a class module is a .cls file or a .NET Class. In a broader sense, a class module is any object-oriented class-looking construct that's not a standard module or a namespace. Examples are UserControls, Forms, Structures and Interfaces.
- A user-defined type declared with the Type statement in classic VB. Not available in VB.NET.
- The Structure..End Structure definition in VB.NET. Not available in classic VB.
- Parent class
- Direct base class (declared via Inherits). In VB.NET, each class has one parent class.
- Ancestor classes
- The parent class and the ancestors of the parent. Includes the entire Inherits tree from a class to the root class.
- Child classes
- Classes that inherit a given class (via Inherits).
- Descendant classes
- The child classes plus the descendants of the children. Includes both direct and indirect Inherits.
Cross-references, call trees and flows
- Reference, cross-references
- A programming entity (such as variable or procedure) is mentioned at another location in the code. Cross-references described
- Call tree
- A call tree shows how the execution flows from a procedure to another, and back. A forward call tree is built in the direction of the control flow. A backward call tree is in the opposite direction. A call tree contains the possible, not the actual, paths for the program flow. A call may execute always, under certain conditions, or never.
- Control flow
- Control flow means the way the execution advances in a system. It results from procedure calls, the handling of events and the implementation of interface members.
Project Graph and Enterprise Diagrams provide ways to visualize control flow as call trees and control flow diagrams. Project Analyzer defines a control flow as a possible control flow. At run-time, a flow may not exist if a procedure call does not execute or an event does not fire.
The firing of (most) events cannot be determined by reading the source code. Thus, events are not always included in the control flow. As an example, the showing a form is not included in a control flow.
- Data flow
- Data flow means how data is used in a system.
Project Graph and Enterprise Diagrams provide ways to visualize data flows between modules.
- Data flows in to a module when the module reads an external variable or when it calls an external procedure that returns values via its parameters or the function return value.
- Data flows out of a module when the module writes an external variable or when it passes a parameter to an external procedure that reads the parameter.
Data flow is a run-time event. Therefore, the use of a constant value is not data flow.
Project Analyzer defines a data flow as a possible data flow. At run-time the flow may not exist because
- a value written to a variable is not read
- a passed parameter value is not used
- an optional parameter value is not passed, instead, the default value is used
- a function return value is not used
- an instruction does not execute, or it has no effect, at run-time
When it cannot be detected whether a parameter value is read or written in a procedure for which the source code is not available, it is assumed both read and written.
- File dependency
- A file depends on another if it requires parts of the other file to compile or run. File dependencies include the following types of uses: any use of procedure name, access to global or module-level variable, access of control placed on form, use of name of module, form, Type, Enum, class, structure, interface, namespace or the like, use of constant or enum constant. Other depedencies come from UserControls placed on forms, PropertyPages required by UserControls, and library files required by Declare statements.
The direction of a file dependency is user file → required file.
The direction may be different from the direction of control or data flow.
||Procedure. The blue ball denotes that the code has a wider scope than Private. It may be Protected, Friend, Protected Friend or Public. If there is no blue ball, it is Private.
||Dead procedure. The red line means that the code is dead.
||Procedure may execute by external call. The violet × means the procedure has not been found to execute, but it may execute as a result of a call by another, unanalyzed project. The deadness status is thus unknown.
You can find all the icons described inside Project Analyzer itself. See Legend in the Help menu.
©Aivosto Oy Project Analyzer Help