Motivation

Part of the power of Smalltalk is its dynamic binding characteristic.
The programmer does not need to declare the classes of objects
referenced in method definitions. This capability enhances
reusability and accelerates proto-typing. Unfortunately, the tradeoff
is that Smalltalk applications are more prone to run-time errors.
Because the Smalltalk compiler does not check the validity of messages
sent to objects within a method definition, errors such as sending
undefined or misspelled messages can not be caught during compilation.
While not all mistakes can be trapped, many can be caught by
inspecting of the source code.

We have implemented a Smalltalk class to inspect the source string of
method definitions to look for undefined and misspelled selectors, and
to deduce the possible set of classes that referenced objects could
belong to.

Message Validation

Each method definition generally contain the following objects:

Self

Super

Argument variables

Temporary variables

Instance variables

Class Instance variables

Class variables

Global variables

Pool variables

The first step in validating messages within a method definition is
parsing. We must be able to identify each object and the messages
being sent to them. This is most easily done for self and super
because we already know the classes they belong to. For other
objects, more advanced string parsing techniques are necessary. After
parsing we stored our parsed messages in a dictionary where the key is
the name of the object variable and the value is a collection of
messages sent to the object variables within the method.

The next step is to go through the dictionary one object variable at a
time. For each message sent to the object variable, we first check to
see that all the messages sent to the object are defined. We remove
the undefined messages from the collection and print the error to the
transcript. For each of the messages remaining in the collection, we
find the set of possible classes that can understand the message, one
set for each message. After having generated all the sets, we find
the intersection. The set of classes in the intersection shows the
possible classes the object could belong to. If the intersection is
empty, then the object cannot belong to any defined class. We print
the class in the intersection to the transcript and warn of any empty
intersections.

The implementation is simplified for self and super since we already
know the classes they belong to. All that we need to do is to make
sure that all the messages sent to self or super are understood by
their respective classes.

Examples

We now provide some common mistakes found in method definitions.
Smalltalk compilers overlook these mistakes during compilation thereby
suppressing their malfeasance until run-time. We will show how our
validation technique would trap these errors using the source string
of method definitions.

Suppose that we have a class called Person with two methods defined,
sleep and walk, and we would like to define a third method called
sleepWalking as follows

sleepWalking
self sleep
self walk.

The Smalltalk compiler would compile this method without any
complaints. If we then pass this method through the validation
process, the transcript would show the following error messages

ERROR: Method sleepWalking in Class: Person has the following problems
***Messages not understood by any class of objects!***
self

If we recheck the method definition, we would observe that we
neglected to put a period after sleep, which leads the validation
procedure to treat self as a single method being sent to self sleep.

Besides missing periods, another common problem is misspelling of
selectors. Suppose we typed the following to define sleepWalking

sleepWalking
self sleeep.
self walk.

Again, Smalltalk would compile the method without detecting any
problems, but the validation process would generate the following
error messages in the transcript

ERROR: Method sleepWalking in Class: Person has the following problems
***Messages not understood by any class of objects!***
sleeep
***Messages not understood by self.***
sleeep

We now provide an example where the validation process deduces a
possible set of classes that a variable can belong to based on the
messages it receives. Suppose we have a class with the following
method definition