One for the bad tpyists

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

One for the bad tpyists

Ian Bartholomew
Here's a useful little addition for anyone who, like me, tends to type
faster than they should. Some typing errors, misspelt variable names for
example, are caught by the compiler. However, mistakes in the spelling of
selector names get past the compiler and result in DNU walkbacks.

After making the following changes a check is made, when a method is saved,
to ensure that all the selectors referenced by the method actually exist. If
not a warning is flagged on the ClassBrowser/MethodBrowser status bar giving
the name of the missing method(s).

Two important points
- It may be that you have just not yet got round to defining the missing
method and because of this the patch works as an advisor only. It does not
affect the compiled method or the operation of the browser and doesn't make
you acknowledge the warning.
- It only checks that a method is defined _somewhere in the image for each
selector. It makes no attempt to ensure that each selector is being used on
a receiver that can understand it.

It is important that you add the first two methods below _before_ modifying
the third

ADD
MethodBrowser>>checkUndefined
 | undefined behaviors |
 behaviors := Class allBehaviors. "cache for performance"
 undefined := self method messages reject: [:eachMessage |
  behaviors anySatisfy: [:eachClass | eachClass includesSelector:
eachMessage]].
 undefined isEmpty ifTrue: [^self].
 sourcePresenter showUndefined: undefined asSortedCollection

ADD
SmalltalkWorkspace>>showUndefined: aCollection
 (self errorModel notNil and: [self errorModel value isNil])
  ifTrue: [ | stream |
   stream := String writeStream.
   stream
    nextPutAll: ' undefined selector';
    nextPutAll: (aCollection size > 1 ifTrue: ['s:'] ifFalse: [':']);
    space.
   aCollection do: [:each | stream print: each; space].
   self errorModel value: (Warning new messageText: stream contents).
   Sound errorBeep]

MODIFY the following method by adding the following line before the return
statement at the end of the method. The last two lines of code (ignoring the
comment) should read as below

MethodBrowser>>saveMethodInClass: class categories: categories
.....
 newMethod notNil ifTrue: [self checkUndefined].
 ^newMethod.

If you now add a method

fred
    self bert

you should get a warning that #bert is undefined but the compilation, and
the addition of the method to the class, should still work as normal.

Ian


Reply | Threaded
Open this post in threaded view
|

Re: One for the bad tpyists

Blair McGlashan
Ian

"Ian Bartholomew" <[hidden email]> wrote in message
news:92vij7$m4u$[hidden email]...
> Here's a useful little addition for anyone who, like me, tends to type
> faster than they should. Some typing errors, misspelt variable names for
> example, are caught by the compiler. However, mistakes in the spelling of
> selector names get past the compiler and result in DNU walkbacks.
> ...

Another great idea. One small suggestion for a minor improvement. If you use
'Smalltalk allBehaviors' rather than 'Class allBehaviors' it will run a bit
faster because the sys dictionary caches the current set of classes.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: One for the bad tpyists

John Aspinall-2
In reply to this post by Ian Bartholomew
Excellent! Or how about this - no warning message, but instead the offending
selectors are highlighted in red:

---

Modifiy CompiledMethod>>getColoredSource

getColoredSource: aString
 "Private - Answer an RTF format source string from the source, aString,
 for the receiver."

 | coloredSource richText behaviors undefined |

 coloredSource := self compilerClass syntaxColorOfMethod: aString in: self
methodClass.
 richText := coloredSource rtf.

 behaviors := Class allBehaviors. "cache for performance"
 undefined := self messages reject:
  [:eachMessage | behaviors anySatisfy: [:eachClass | eachClass
includesSelector: eachMessage]].

 undefined do:
  [ :eachSelector || stem |
  stem := eachSelector copyFrom: 1 to: (eachSelector indexOf: $: ifAbsent:
[eachSelector size]).
  richText := richText copyReplaceAll: (' ', stem) with: (' {\cf3 ', stem,
'}')].

 coloredSource rtf: richText.

 ^coloredSource

---

The colour highlighting is not completely foolproof - it (intentionally)
only marks the first part of a multi-argument selector, and can incorrectly
highlight parts of correct selectors. But for a dumb string-based method
it's not too bad.

John Aspinall



Ian Bartholomew <[hidden email]> wrote in message
news:92vij7$m4u$[hidden email]...
> Here's a useful little addition for anyone who, like me, tends to type
> faster than they should. Some typing errors, misspelt variable names for
> example, are caught by the compiler. However, mistakes in the spelling of
> selector names get past the compiler and result in DNU walkbacks.
>
> After making the following changes a check is made, when a method is
saved,
> to ensure that all the selectors referenced by the method actually exist.
If
> not a warning is flagged on the ClassBrowser/MethodBrowser status bar
giving
> the name of the missing method(s).
>
> Two important points
> - It may be that you have just not yet got round to defining the missing
> method and because of this the patch works as an advisor only. It does not
> affect the compiled method or the operation of the browser and doesn't
make
> you acknowledge the warning.
> - It only checks that a method is defined _somewhere in the image for each
> selector. It makes no attempt to ensure that each selector is being used
on
> a receiver that can understand it.
>
> It is important that you add the first two methods below _before_
modifying

> the third
>
> ADD
> MethodBrowser>>checkUndefined
>  | undefined behaviors |
>  behaviors := Class allBehaviors. "cache for performance"
>  undefined := self method messages reject: [:eachMessage |
>   behaviors anySatisfy: [:eachClass | eachClass includesSelector:
> eachMessage]].
>  undefined isEmpty ifTrue: [^self].
>  sourcePresenter showUndefined: undefined asSortedCollection
>
> ADD
> SmalltalkWorkspace>>showUndefined: aCollection
>  (self errorModel notNil and: [self errorModel value isNil])
>   ifTrue: [ | stream |
>    stream := String writeStream.
>    stream
>     nextPutAll: ' undefined selector';
>     nextPutAll: (aCollection size > 1 ifTrue: ['s:'] ifFalse: [':']);
>     space.
>    aCollection do: [:each | stream print: each; space].
>    self errorModel value: (Warning new messageText: stream contents).
>    Sound errorBeep]
>
> MODIFY the following method by adding the following line before the return
> statement at the end of the method. The last two lines of code (ignoring
the

> comment) should read as below
>
> MethodBrowser>>saveMethodInClass: class categories: categories
> .....
>  newMethod notNil ifTrue: [self checkUndefined].
>  ^newMethod.
>
> If you now add a method
>
> fred
>     self bert
>
> you should get a warning that #bert is undefined but the compilation, and
> the addition of the method to the class, should still work as normal.
>
> Ian
>
>
>
>
>
>
>
>
>
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: One for the bad tpyists

jWarrior
we (jwars) use the va assist pro product for visual age smalltalk by eric
clayberg that does exactly this and it is quite nice. right up there
with color syntax highlighting and (dare I say) formatting.

good job, ian.  the va product also has a means of looking up
all methods with mis-spellings.

"John Aspinall" <[hidden email]> wrote in message
news:92vttf$89n4e$[hidden email]...
> Excellent! Or how about this - no warning message, but instead the
offending

> selectors are highlighted in red:
>
> ---
>
> Modifiy CompiledMethod>>getColoredSource
>
> getColoredSource: aString
>  "Private - Answer an RTF format source string from the source, aString,
>  for the receiver."
>
>  | coloredSource richText behaviors undefined |
>
>  coloredSource := self compilerClass syntaxColorOfMethod: aString in: self
> methodClass.
>  richText := coloredSource rtf.
>
>  behaviors := Class allBehaviors. "cache for performance"
>  undefined := self messages reject:
>   [:eachMessage | behaviors anySatisfy: [:eachClass | eachClass
> includesSelector: eachMessage]].
>
>  undefined do:
>   [ :eachSelector || stem |
>   stem := eachSelector copyFrom: 1 to: (eachSelector indexOf: $: ifAbsent:
> [eachSelector size]).
>   richText := richText copyReplaceAll: (' ', stem) with: (' {\cf3 ', stem,
> '}')].
>
>  coloredSource rtf: richText.
>
>  ^coloredSource
>
> ---
>
> The colour highlighting is not completely foolproof - it (intentionally)
> only marks the first part of a multi-argument selector, and can
incorrectly

> highlight parts of correct selectors. But for a dumb string-based method
> it's not too bad.
>
> John Aspinall
>
>
>
> Ian Bartholomew <[hidden email]> wrote in message
> news:92vij7$m4u$[hidden email]...
> > Here's a useful little addition for anyone who, like me, tends to type
> > faster than they should. Some typing errors, misspelt variable names for
> > example, are caught by the compiler. However, mistakes in the spelling
of
> > selector names get past the compiler and result in DNU walkbacks.
> >
> > After making the following changes a check is made, when a method is
> saved,
> > to ensure that all the selectors referenced by the method actually
exist.
> If
> > not a warning is flagged on the ClassBrowser/MethodBrowser status bar
> giving
> > the name of the missing method(s).
> >
> > Two important points
> > - It may be that you have just not yet got round to defining the missing
> > method and because of this the patch works as an advisor only. It does
not
> > affect the compiled method or the operation of the browser and doesn't
> make
> > you acknowledge the warning.
> > - It only checks that a method is defined _somewhere in the image for
each

> > selector. It makes no attempt to ensure that each selector is being used
> on
> > a receiver that can understand it.
> >
> > It is important that you add the first two methods below _before_
> modifying
> > the third
> >
> > ADD
> > MethodBrowser>>checkUndefined
> >  | undefined behaviors |
> >  behaviors := Class allBehaviors. "cache for performance"
> >  undefined := self method messages reject: [:eachMessage |
> >   behaviors anySatisfy: [:eachClass | eachClass includesSelector:
> > eachMessage]].
> >  undefined isEmpty ifTrue: [^self].
> >  sourcePresenter showUndefined: undefined asSortedCollection
> >
> > ADD
> > SmalltalkWorkspace>>showUndefined: aCollection
> >  (self errorModel notNil and: [self errorModel value isNil])
> >   ifTrue: [ | stream |
> >    stream := String writeStream.
> >    stream
> >     nextPutAll: ' undefined selector';
> >     nextPutAll: (aCollection size > 1 ifTrue: ['s:'] ifFalse: [':']);
> >     space.
> >    aCollection do: [:each | stream print: each; space].
> >    self errorModel value: (Warning new messageText: stream contents).
> >    Sound errorBeep]
> >
> > MODIFY the following method by adding the following line before the
return

> > statement at the end of the method. The last two lines of code (ignoring
> the
> > comment) should read as below
> >
> > MethodBrowser>>saveMethodInClass: class categories: categories
> > .....
> >  newMethod notNil ifTrue: [self checkUndefined].
> >  ^newMethod.
> >
> > If you now add a method
> >
> > fred
> >     self bert
> >
> > you should get a warning that #bert is undefined but the compilation,
and

> > the addition of the method to the class, should still work as normal.
> >
> > Ian
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
>
>
>
>
>
>
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: One for the bad tpyists

Ian Bartholomew
Donald,

> good job, ian.  the va product also has a means of looking up
> all methods with mis-spellings.

I posted something like that a few months ago. It was a little browser that
had two options, one showed a list of all selectors that were used but not
implemented (and the method(s) that referenced each one) and the other
showed all the methods that were implemented but not used.

It wasn't as useful as I though it might be as there were too many things
that legitimately fell into one of the two categories but were not actually
errors. References to dynamically created methods is structure classes for
example.

Dolphin4 has made some changes in this area so I don't know if the app still
works or can be improved - I can check if anyone is interested.

Ian


Reply | Threaded
Open this post in threaded view
|

Re: One for the bad tpyists

Ian Bartholomew
In reply to this post by John Aspinall-2
John,

> Excellent! Or how about this - no warning message, but instead the
offending
> selectors are highlighted in red:

Neat, I hadn't thought of doing it that way.  I'm not completely convinced
about the advisability of modifying the coloured source like that though -
there might well be occasions where I want the source but wouldn't want
anything highlighted.

Something to bear in mind anyway - thanks

Ian


Reply | Threaded
Open this post in threaded view
|

Re: One for the bad tpyists

Doug Way-3
In reply to this post by Ian Bartholomew
In article <92vij7$m4u$[hidden email]>,
  "Ian Bartholomew" <[hidden email]> wrote:
> Here's a useful little addition for anyone who, like me, tends to type
> faster than they should. Some typing errors, misspelt variable names
for
> example, are caught by the compiler. However, mistakes in the spelling
of
> selector names get past the compiler and result in DNU walkbacks.
>
> After making the following changes a check is made, when a method is
saved,
> to ensure that all the selectors referenced by the method actually
exist. If
> not a warning is flagged on the ClassBrowser/MethodBrowser status bar
giving
> the name of the missing method(s).

Squeak actually does something similar to this, except that if you have
a misspelled selector, it warns you and brings up a list of similarly
spelled selectors in the image for you to choose from.  If you pick a
different one, it replaces the selector(s) in your method and goes ahead
and compiles it.

This is a pretty cool feature, although in a way it's nice that your
status bar warning does not interrupt you if you're just compiling a
method which sends a not-yet-implemented message.

- Doug Way
  (at riskmetrics dot com)


Sent via Deja.com
http://www.deja.com/


Reply | Threaded
Open this post in threaded view
|

Re: One for the bad tpyists

Costas Menico-2
On Wed, 03 Jan 2001 23:16:17 GMT, Doug Way <[hidden email]> wrote:

>In article <92vij7$m4u$[hidden email]>,
>  "Ian Bartholomew" <[hidden email]> wrote:
>> Here's a useful little addition for anyone who, like me, tends to type
>> faster than they should. Some typing errors, misspelt variable names
>for
>> example, are caught by the compiler. However, mistakes in the spelling
>of
>> selector names get past the compiler and result in DNU walkbacks.
>>
>> After making the following changes a check is made, when a method is
>saved,
>> to ensure that all the selectors referenced by the method actually
>exist. If
>> not a warning is flagged on the ClassBrowser/MethodBrowser status bar
>giving
>> the name of the missing method(s).
>
>Squeak actually does something similar to this, except that if you have
>a misspelled selector, it warns you and brings up a list of similarly
>spelled selectors in the image for you to choose from.  If you pick a
>different one, it replaces the selector(s) in your method and goes ahead
>and compiles it.
>
>This is a pretty cool feature, although in a way it's nice that your
>status bar warning does not interrupt you if you're just compiling a
>method which sends a not-yet-implemented message.

Actually I really like this with Squeak. It  can be used for
intellisense or code completion. I wonder if they use the soundex
algorithm.

The only downside to this is that you must make a selection or fix it
in case your method is not implemented. Maybe the solution in this
case would be to have the option in a dialog box of defining an empty
method and give it the class name or self.

I think between this and Ian's code, Dolphin could legally claim it
has code completion capabilities!

Costas

P.S. As I am still not up to speed with programming the tools, I
apologize for not being able to implement code for this.


Reply | Threaded
Open this post in threaded view
|

Re: One for the bad tpyists

Ian Bartholomew
In reply to this post by Ian Bartholomew
Slight update to the previous posting for anyone using the undefined method
check. When editing using the MethodBrowser it is possible for the method to
disappear before the undefined check is reached (after renaming a class for
example). The following modified method prevents the walkback in those
situations and also includes Blair's previous suggestion.

MethodBrowser>>checkUndefined
    | undefined behaviors |
    self method isNil ifTrue: [^self].
    behaviors := Smalltalk allBehaviors. "cache for performance"
    undefined := self method messages reject: [:eachMessage |
        behaviors anySatisfy: [:eachClass |
            eachClass includesSelector: eachMessage]].
    undefined isEmpty ifTrue: [^self].
    sourcePresenter showUndefined: undefined asSortedCollection

Ian