LSCalls12/14/2005

The origin of LSCalls was a need that I had to get a clearer picture of how the code in Teamstudio Build Manager was being used. Since it's inception the code (almost 99% LotusScript) had grown in complexity quite a bit. As with any project functions have been added, removed and changed a lot. The problem was that I knew that some code was not being used but it was a pretty painstaking process to find functions that were no longer being called. So, initially that was the point of LSCalls (hence the name). It turned out to be extremely fast to run through all the code and find the references. It's also didn't end up being very difficult to put together since Script Browser does this already, it just doesn't keep a track of the number of times a function is called. The other thing I was able to do was produce an accurate call tree. For each function I can see what other functions are being referenced and on what line.


So with that done I thought to myself, why not try it on other symbols as well like variables and labels? After spending a little more time I was able to add variable references as well. Warnings has been something I have always thought was missing from the script compiler. I've seen a lot of LotusScript in my time that is littered with unused variables. Not only does it make the code hard to read, but it's even harder to maintain. Can you delete that dim? Are you SURE it's not being used? If it is used are you sure you know where?

For Example:
Sub
foo( sName as String )
Dim
x As Integer
Dim
y As Integer

[ lots of code here.... ]
[ lots of code here.... ]
[ lots of code here.... ]
[ lots of code here.... ]

label1:
Print
x
End Sub

Gives you this:
Symbol Y (Integer) found in 'FOO' references: 0
Symbol label1 (Label) found in 'FOO' references: 0
Parameter sName (String) found in 'FOO' references: 0

The other thing that LSCalls will tell you in regards to variable references are times when a symbol is 'read' from before it is 'written' too.
For example:
Sub
foo
Dim
x As Integer
If
x = 1 Then
Print
"X is one"
End If

End Sub

Gives you this:
Symbol X (Integer) found in 'FOO' was read before written on line 4

In the above function, the variable X is read from in the ‘If’ statement. Since X was never initialized (written to) after it is declared lscalls will flag this as a potential error. This particular type of warning can be benign since LotusScript will initialize basic types like ‘integers’ for you. In this case 'X' is initialized to zero and the if will always be false to it will never be called... not a big deal, but it makes the code hard to read and what was the programmer really trying to accomplish? It's probably something that should be investigated.

However, classes are not initialized for you so this script would generate a runtime error:
Sub
foo
Dim
s As NotesSession
If
s.Platform = "Windows/32" Then
Print
"Running on windows"
End If

End Sub

Gives you this:
Symbol S (Class) found in 'FOO' was read before written on line 3

In either case, there is a bug in the code that should be fixed. In the first example nothing bad will happen, but in the second example:

.
That being said, I think what you really want is something that tells you at the time when you are actually editing the code like this.....
but........ we can talk about that later....


To use lscalls, you must run it from your notes executable directory.

UPDATE: When I first released LSCalls, a fellow blogger by the name of Chad Schelfhout put together a nifty Notes database to call and process the output of LS Calls. This is a really great tool to help analyze the data coming out of LSCalls and also makes it really convenient to use the tool itself. You can download it here: http://www.chadsmiley.com/chadsmiley/home.nsf/d6plinks/CHAY-6M46Y7



Click here to download LSCalls

Options:
-v Report all script function calls.
This option will print a line ever time a function call is encountered in the script code.
For example, in the form called ‘memoform’ in the ‘Initalize’ function, a reference to the function ‘globalfunction’ was found on line 3 . lscalls also reports where the referenced function was defined. In this case the function comes from the ‘Globals’ section of the form itself.
Ex:
memoform :
In Function INITIALIZE:
Fn GLOBALFUNCTION called on line: 3 - Defined in: (GLOBALS)MEMOFORM
-a Report all reference statistics.
This option will include all functions and variables and how many times each was called. If this option is omitted, then only functions and variables with zero calls are included in the report.
-d Include destructors in results.
This option prevents the ‘Delete’ functions of classes from showing up in the report. Lscalls cannot tell when a destructor is called from the LotusScript code due to the instance going out of scope. The only time lscalls can tell is if you call the destructor directly.
-s Report unreferenced variables.
This option includes all variables that have zero references in addition to functions.
For example, the following function :
Sub
foo
Dim
x As Integer
Dim
y As Integer
label1:
Print
x
End Sub

Gives you this:
Symbol Y (Integer) found in 'FOO' references: 0
Symbol label1 (Label) found in 'FOO' references: 0
-S Report all variable references.
This is similar to the ‘-v’ option but applies to variables.

-r
Report all variable read before write errors.
This option reports each time a variable is ‘read’ from before it is written to. For example:
Sub
foo
Dim
x As Integer
If
x = 1 Then
Print
"X is one"
End If

End Sub

Gives you this:
Symbol X (Integer) referenced on line: 4 - Read before write

In the above function, the variable X is read from in the ‘If’ statement. Since X is never initialized (written to) after it is declared lscalls will flag this as a potential error. This error can be benign since LotusScript will initialize basic types like ‘integers’ for you. However, classes are not initialized for you so this script would generate a runtime error:
Sub
foo
Dim
s As NotesSession
If
s.Platform = "Windows/32" Then
Print
"Running on windows"
End If

End Sub


In either case, there is a bug in the code that should be fixed.
-t Include unreferenced type members in the report.
This option will include all unreferenced members of a TYPE in the report.
-c Print call tree.
This option will print out a list of all functions in the database followed by a list of functions that are called by that function.
Example:
-------------------------------------
Call tree:
-------------------------------------
formglobals (15E)
INITIALIZE
'GLOBALFUNCTION' called on line: 3 - Defined in: (GLOBALS)FORMGLOBALS
formglobals (Globals) (15E)
INITIALIZE
'TESTING1::NEW' called on line: 2 - Defined in:
test (14E)
TEST_BYNAME
'MYCLASS::NEW' called on line: 3 - Defined in: CLASS
TEST_VARIANT
'MYCLASS::NEW' called on line: 3 - Defined in: CLASS
-------------------------------------
-e Report on all functions that don't have an error handler.
-o [filename] Send results to CSV file.
This option writes a Comma Separated Value of the output. You can import this into Excel for example and be able to sort the different columns



Contact Me
Free tools!
The BlogRoll
Lotus Domino ND6 RSS News Feed netcraft Lotus Geek Chris. A. Brandlehner CoComment Integrated
Monthly Archive
Photo Albums