TclChecker, based on
procheck and included in
Tcl Dev Kit, is a tool for
static analysis.
Documentation edit
- official reference ,version 5.4
Description edit
Find errors in Tcl scripts before they are run.- Uncover problems in new scripts, scripts from older versions of Tcl/Tk, or scripts ported from another operating system.
- Assess the quality of a body of Tcl code.
- Quickly examine large Tcl files.
- Find potential incompatibilities to guide upgrades to current Tcl, Tk and incr Tcl releases.
TclChecker provides options to control syntax checking output, as well as recommend corrected code for common coding mistakes. It includes support for Tcl
8.6.
Integrates with
tcldebugger and the
Komodo IDE.
Additional .pcx files for Tcl extensions edit
LV: So, has anyone created the necessary
.pcx files to allow tclchecker to check the more common tcl extensions?
TDK comes with some documentation on creating these files. However, they are relatively complex. It would be useful to try and take the info from the doc and try to write a usable .pcx file, just to work out the kinks of how things work. It seems pretty complex.
AK: I have
.pcx files for some of the packages in
Tcllib. I will commit them (incrementally) to Tcllib. They will require version 4.1 of
Tcl Dev Kit.
Musings (a kind of review) edit
[name redacted]: I tried TclChecker on some of my longer programs today (2014-01-11). I'm not quite sure how I feel about it. TC didn't find very much to complain about, which I suppose could be because I'm just that good -- OTOH, it could mean that TC fails to detect anything beyond the most obvious blunders. So, what
did it find?
- I sometimes omit the default clause in a switch command. Yikes.
- I sometimes omit -- before the string argument in a switch command. Oops. (TC did not complain about me omitting the -- in a regexp command, however, even when I used a variable dereference for the exp value.)
- I tend to omit the optional level argument to upvar.
- I occasionally use constructs like set $varName foo or variable $varName foo, for instance when initializing a bunch of variables in one action, or append $varName foo if I need to select which variable to append to. TC doesn't like any of these, but is satisfied when I change $varName to [set varName] (which does make sense, since that's a lot less likely to be a mistake). It does recognize and accept the idiom upvar 1 $varName myVar.
- A lot of undefined variables that actually were defined: TC got confused in a couple of cases when variables were being set using regexp (there was some indirection involved) or using dict with. (TC is a static analysis tool after all, so I don't really blame it for not figuring it out here.)
- I tend to omit the braces around the condition in an if command if all of the condition is a variable dereference, a command invocation, or a boolean literal such as no or 0 (mostly used when excluding sections of code "Bauersachs braces"-style). TC gets concerned about "avoid[ing] double substitution and/or performance degradation".
(
List roughly sorted in order of what I feel is justified to complain about. Do note that I'm not questioning if TC is correct in making these observations (it is: it's simply doing what a static analysis tool should do, no more, no less): my talking back to TC is mostly me wondering aloud whether or not a static analysis tool would be of any help to me.)
1 and 2: yes, those are valid points, I fixed those cases immediately and resolved to keep that in mind (even more than I already did) in the future (I was taught not to do #1 in the
early 1980s, and have taught students of my own not to do it: I don't know why I still miss this sometimes).
3: Um, OK, maybe that's valid, even though I can't see myself passing in a variable name starting with a digit or a hash sign.
4: What's the problem, really? (Sure, sometimes it
is a bug-causing mistake, and a serious one at that, but it wasn't in any of these cases.) I did make the change to
[set varName] while negotiating with TC, but I'm not sure I'll change my ways in the future.
5: This is mainly TC's problem, not mine. I mean, if a variable really is undefined at the point of use, I will notice it not by running a checker, but by the program, you know,
crashing. Unfortunately, short of inserting an excluding pragma or a
set command to pre-define the variable there doesn't seem to be a way to arrange the source to avoid this kind of false positive.
6. Yes, that might be causing bugs, but it's not very likely, is it? At least, I doubt that the string "no" will end up giving me double substution or performance problems. And if your conditions evaluate to something other than a boolean value in the first place, maybe Tcl isn't for you. (Alternatively, you're writing code that
relies on that double substitution, in which case you don't want the braces anyway.)
Also, even though I specified version 8.6, TC didn't recognize the
lmap command. Neither did it know about
cmdline. It
did check
oo for some reason (I wasn't using OOP).
Namespace ensembles seem to be a mystery to it.
I think I will test TC once more while actually creating a program (as opposed to trying it on working, more-or-less error-free programs). Maybe it will prove more useful in that situation.
In summary: if I were the manager of a team of programmers I'd insist on everyone using TC before checking in code because it would be good practice (a work environment is no place for idiosyncrasies or code that is even remotely dubious). For myself as a hobby programmer, I'm good if the program runs correctly (and I do test them at least informally, out of habit). While I suppose TC can sometimes be really helpful, it wasn't at this time: it mostly came dangerously close to just being a bother. I don't think I'm going to spend the money to get the license for it.
RLE 2014-01-11: (Re #6 above:) This is a potential issue in several ways. One, if at some much later point in time the variable contains something much more dangerous than "no", you've got a "surprise" bug that can be hard to track down. Second it interferes with bytecode compiling [
1] [
2]. Generally it is better to get into the habit of always bracing the expression to an if, then you are less likely to forget the braces when you do actually need them.
[name redacted]: Yes, but if the variable changes value to something else than a boolean value, I'm in trouble regardless of whether I use braces or not. I usually try to keep my variables short-lived and strictly controlled (which, among other things, means that a non-boolean value has no business being stored in a variable that I have used or will use in a condition). I can't argue with the bytecode compilation issues because that's just the literal truth, but OTOH most of the time compilation doesn't matter very much to me. I agree with you regarding good habits, though (and as a side-note, I religiously brace my
expr arguments). I would probably be far more willing to use braces if the key combination to write them on a Swedish keyboard weren't so awkward: as it is I'm actively looking for ways to avoid them (square brackets and backslashes are also a bother, and still I use LaTeX for most of my writing (gVim helps a bit here, letting me type FTT instead of
\texttt{}) -- am I a masochist?). And yes, I've reconfigured the keyboard to US settings sometimes, but then some other characters are suddenly in uncomfortable locations.
RLE 2014-01-11: Yes, except that "if { $badvar } ..." will generate a runtime error with bad data where as "if $badvar ..." is a potential code injection exploit.
I understand the Swedish keyboard issue. Curly braces are not the easiest on a US keyboard either, but at least they are only a shifted keystroke away. Would it be possible for you to tweak your Swedish keyboard map to let you type curly braces with less fuss/awkwardness?
[name redacted]: (I have an amusing anecdote about programming Pascal on an early type of Swedish keyboard (on an 8-bit CP/M machine) that didn't have
any kind of braces or square brackets, or, come to think of it, backslash or dollar sign -- had Tcl been invented by then I'd had had a hard time coding it (it
couldn't have those: ISO 646-SE-C 7-bit character set, y'know), and how Sweden's most popular lesbian singer-songwriter helped me manage anyway, but this margin is too narrow to contain it.) I've toyed with the idea of temporarily switching the F8--F12 function keys to { [ ] } \ (since they are directly above where they're located now) but never really looked into the matter. There is also the aspect that I use two keyboards during workdays, at work and at home, and work won't allow me to tamper even with the keyboard map (I'm currently putting together a request to have Tcl installed on my work computer, but I'll have to insulate that snowball very heavily before I throw it through that hell).
[name redacted] 2014-12-12: For all my griping about not wanting to put braces around a condition, I seem to have acquired the habit of doing so since then. So much so, in fact, that I find that it now irritates me when other people's code has
if $badvar invocations. Same thing with explicitily giving the level argument to
upvar. Life is like that sometimes.