Problem detection finds coding problems. Comment directives hide them. When you wish to ignore problems in a certain section of code, you write a comment directive in your code. Comment directives are specially formatted comments. Example: '$PROBHIDE ALL
hides all problems on a single line.
With comment directives you can:
GoTo
statement while getting warned about the rest of them.For a start, let's see what a typical directive looks like:
'$PROBHIDE GOTO
That's it! This will hide a "Goto statement found" problem for a line. Now let's look at the syntax. Comment directives always start with '$
. The '$
prefix marks the start of a comment directive line.
'$ directive [ : directive [ : directive ...]]
The available directives are: PROBHIDE
to hide problems, PROBSHOW
to show them again and END
to finish a BEGIN..END
block.
You can use spaces the way you like. '$PROBHIDE
, ' $PROBHIDE
and '$ PROBHIDE
are the same. Rem
comments can't contain any directives, though. Directives can appear as full-line comments or as end-of-line comments. A full-line directive affects the next line while an end-of-line directive affects the current line (see Scope). Directives can't appear inside other comments. Thus 'Hidden with '$PROBHIDE
is not an acceptable directive.
You can put multiple directives on a line by separating them with a colon ( : ). Usually you would just put a single directive on a line, though.
The PROBHIDE
directive hides problems of one or more types. Use it to disable
problem detection at locations you don't want to change. Syntax:
'$PROBHIDE problemtype [problemtype...] [EXCEPT problemtype [problemtype...] ] [BEGIN]
problemtype
GOTO
for the "GoTo statement found" rule. Certain problemtypes cover two or more related problems. You can also use combination types such as ALL
to hide all problems.EXCEPT problemtype
BEGIN
BEGIN...END
block. The directive affects all code until a matching '$END
directive or end-of-file. If BEGIN
is omitted, the directive affects just one line of code. See Scope.A procedure does not require an error handler. Hide the "Error handler missing" problem for that procedure but show it everywhere else.
'$PROBHIDE NO_ERROR_HANDLER
Sub ProcedureWithoutErrors()
' This procedure needs no error handling
End Sub
A procedure is dead at the moment but you don't want to remove it. You want to flag the procedure live without hiding any other dead code related problems. Notice how the syntax affects just the next line (the line with the dead procedure problem). Any other lines are not affected and the dead variable problem will thus be shown. Notice that hiding a dead procedure problem propagates down along the call tree.
'$PROBHIDE DEAD
Sub DeadProcedure()
' This procedure should be kept
Dim DeadVariable As Integer
' But this variable should be removed
Call ChildProcedure
End Sub
Sub ChildProcedure()
' This procedure shows up as live
' because it's called by DeadProcedure
' which was flagged live
End Sub
Hide all problems classified as "warning" or "information" until end-of-file.
'$PROBHIDE WARNING INFORMATION BEGIN
code with problems
that I want to hide
Hide all problems in a range of code between BEGIN and END. Keep showing dead code related problems at all locations.
'$PROBHIDE ALL EXCEPT DEAD BEGIN
code with problems
to hide
'$END
show all problems after this point
A Goto statement is acceptable at a certain location. Hide the problem on that specific line. There are two alternative ways to write the same directive: write the comment either on the line with the problem or add it on a new line immediately above it.
Goto 1999 '$PROBHIDE GOTO
'$PROBHIDE GOTO
Goto 1999
Enables (shows) problems that would otherwise be hidden by PROBHIDE
. Syntax:
'$PROBSHOW <problem type> [<problem type> ...] [EXCEPT <problem type> [<problem type> ...] ] [BEGIN]
The syntax is similar to that of PROBHIDE
. You should use PROBSHOW
only inside a PROBHIDE BEGIN...END
block.
Hide all problems in a class, but enable dead code problems after class declarations to remove any dead procedures and local variables/constants.
'$PROBHIDE ALL BEGIN
Dim x, y
Const PI = 3.14
Declare Function ChooseFont Lib "comdlg32.dll" Alias "ChooseFontA" (pChoosefont As CHOOSEFONT) As Long
'$PROBSHOW DEAD BEGIN
Sub MyProc ( x )
End Sub
'$END
...
'$END
Ends a BEGIN...END
directive block. See Scope below for more information.
This obsolete directive marks things as being in use. It is provided for only backward compatibility. Older Project Analyzer versions used to support it until 1999. You should not use this directive any more since future versions may not support it. Project Analyzer replaces it internally as follows:
USED => PROBHIDE DEAD
USED PROC => PROBHIDE DEAD_PROC
USED PARAM => PROBHIDE DEAD_PARAM
How do you work out where to put the directives and what code they will then affect? First of all, look at the problem icons in the hypertext view of Project Analyzer. Your comment directives should be placed to affect the lines with the icons. If your directives don't seem to work, pay attention to the exact line and the scope you're using. There are several alternative ways to define the scope of a comment directive.
'$PROBHIDE DEAD
Dim MyVariable As Integer
A directive on an otherwise empty line affects the immediately following line. In this case, MyVariable is not reported dead.
Dim MyVariable As Integer '$PROBHIDE DEAD
A directive after the code on a given line affects that line. In this case, MyVariable is not reported dead.
'$PROBHIDE DEAD BEGIN
Dim MyVariable As Integer
Dim Text As String
'$END
The directive affects all code starting with BEGIN
up to the next '$END
. In this case, MyVariable and Text are not reported dead.
You may nest multiple BEGIN...END
blocks. You may also omit the END
directive. In that case, the block continues up to end-of-file.
'$PROBHIDE DEAD WHERE expression
To hide problems on specific lines use the WHERE
scope. The directive affects all lines containing expression. Examples:
WHERE reserved
affects lines containing the word reserved
, either as a keyword, in a string literal or in a comment.
WHERE GOTO Quit
affects lines containing GoTo Quit
.
WHERE '
affects lines with a comment (or a string with a ' in it).
WHERE "
affects lines with a string (or a comment with a " in it).
The expression is case insensitive. It can be any string, but a colon (:) cannot be included. If expression contains multiple words, spaces between the words are significant. Spaces before and after expression don't have an effect. The WHERE
directive can exist in any file. It affects all files in the analysis (similar to ANYWHERE
).
'$PROBHIDE DEAD IN_THIS_FILE
To hide problems in an entire file, regardless of which line they affect, use the IN_THIS_FILE
scope. You can put this keyword anywhere in the file to make a directive apply to all lines in the file, also lines before the directive. IN_THIS_FILE
is useful when you need to hide problems at the start of a file, but that area is reserved for comment block and a directive would not look good there.
'$PROBHIDE DEAD IN_THIS_PROJECT
To hide problems in the whole project, regardless of which file they appear in, use the IN_THIS_PROJECT
scope. You can put this keyword anywhere to make a directive apply to all files of the project. This directive may be overridden in each individual file by scopes A–D. On the other hand, it will override ANYWHERE
directives.
IN_THIS_PROJECT
is useful when your regular coding standards don't apply to a certain project. As an example, '$PROBHIDE STYLE IN_THIS_PROJECT
ignores style rules in the project while they are still enabled for other projects.
'$PROBHIDE DEAD ANYWHERE
To hide problems in all files, regardless of which project the file may be in, use the ANYWHERE
scope. You can put this keyword wherever you like to make a directive apply to all files of the analysis. Note that this directive may be overridden in each individual file by scopes A-D and each individual project by scope E.
Use ANYWHERE
instead of IN_THIS_PROJECT
when you want to control an entire analysis instead of an individual project. It will cover all files when analyzing one or more solutions, project groups or a directory tree.
Scope ANYWHERE
has the lowest precendence, IN_THIS_PROJECT
is in the middle. The other scopes are on the highest precedence level.
To avoid any conflicts put all ANYWHERE
directives in a single file. The precedence of conflicting ANYWHERE
directives mixed in different files is undefined. The same goes for conflicting IN_THIS_PROJECT
directives. You may want to put them in a global declarations file to make them easier to manage.
Directives coming later override directives on preceding lines. Thus, you can always override a previous directive by writing a new directive after it. As an example, you can have a '$PROBHIDE ALL
early in the file and then override it with a '$PROBSHOW DEAD IN_THIS_FILE
later. In this case, the later PROBSHOW
has higher precedence and will override the PROBHIDE
for dead code problems.
If you don't want a directive to override others, use the EXCEPT
keyword. As an example, '$PROBSHOW ALL EXCEPT STYLE IN_THIS_FILE
would show all other problems but it wouldn't have any effect on style related problems. Style problems would be entirely controlled by other directives, should any exist.
general.bas:
'$PROBHIDE STYLE IN_THIS_PROJECT
causes style related problems to be ignored in a project where style doesn't matter.
important.bas:
'$PROBSHOW ALL IN_THIS_FILE
enables all problems in important.bas regardless of any setting in general.bas.
'$PROBHIDE TYPECHAR WHERE &
This example disables the rules "Function/constant/variable with type character" on lines containing an ampersand (&). The line exceptionally allows declarations such as Dim Number&
instead of Dim Number As Long
, but only with & and no other type characters.
'$PROBHIDE GOTO SINGLELINEIF WHERE Goto Quit
This example allows the use of the Goto keyword to jump to Quit. In addition, it also allows a single-line If..Then
to exist on the same line. Code that would be allowed: If somecondition Then Goto Quit
'$PROBHIDE SINGLELINEIF ANYWHERE
'$PROBSHOW SINGLELINEIF WHERE Else
This example allows a single line If..Then
but not a single-line If..Then..Else
.
You can flag a procedure as live code in several ways. The recommended way is by '$PROBHIDE DEAD
or '$PROBHIDE DEAD_PROC
.
Hiding a dead procedure problem flags the affected procedure as live code. What is more, also the procedures it calls are flagged live, down along the entire call tree. Consider a call tree such as A → B → C. If you flag A as a live procedure, also B and C will show up as live. Thus, using '$PROBHIDE
to hide one dead procedure also propagates downwards in the call tree. You can mark just the root procedure as live and Project Analyzer will take care of the rest. The call tree propagation only affects procedures. Variables, classes or any other code is not affected.
There's a command line option that tells Project Analyzer to ignore all comment directives. Start Project Analyzer like this:
project.exe /NOCDIRECTIVES
Use this option to detect all problems even if $PROBHIDE
has been used to hide some of them. You can also use it if your code happens to have existing lines that start with '$PROBHIDE
, '$PROBSHOW
or '$USED
.
PROJECT_ANALYZER
is a special built-in "compiler constant" in Project Analyzer. It allows you to tweak the code analysis. You can add missing definitions or exclude sections from being analyzed. During code analysis, PROJECT_ANALYZER = True
. In Visual Basic, PROJECT_ANALYZER
is not defined and thus evaluates to False
.
PROJECT_ANALYZER
is not a comment directive. It's a constant for #If..#ElseIf..#Else..#End If
.
The following trick lets you write code that won't be analyzed at all. You can also add code for the purpose of code analysis only.
#If PROJECT_ANALYZER Then ' Analyze what would happen with this FakeCall #Else ' This runs but won't be analyzed SecretCall #End If
The next trick lets you run your code with late binding, but analyze it as if it were early-bound.
#If PROJECT_ANALYZER Then ' Analyze early-bound calls only Dim o As MyClass #Else ' Run with late binding Dim o As Object #End If
Versions. Suppose your code compiles two versions of the same program. To compile version 1, you set VERSION=1
in your project settings. To compile the other version, you set VERSION=2
. Now, you exclude and include sections of code with #If
to compile the 2 versions. This causes problems in the analysis, because Project Analyzer should read your code in its entirety and not just one of the versions.
The following trick lets you compile several versions of your program while keeping Project Analyzer analyzing the full code.
#If VERSION = 1 Or PROJECT_ANALYZER Then Version 1 code goes here #End If #If VERSION = 2 Or PROJECT_ANALYZER Then Version 2 code goes here #End If
Tweak metrics. Suppose you have a large section of generated code that shouldn't be counted in the logical lines of code (LLOC) metric, because it exaggerates the size of your program. By adding the generated code in a False block you exclude it from LLOC, even when it still compiles and runs just fine.
#If Not PROJECT_ANALYZER Then excluded code goes here #End If