Very strange thing: a lowercase string is pased as argument to a method with first letter in uppercase without anyone asking for it

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

Very strange thing: a lowercase string is pased as argument to a method with first letter in uppercase without anyone asking for it

Sebastián Sastre
Hi guys,

 there is something really strange here. I'm watching with the debugger
a method as the following:

>>createComponents

        super createComponents.

        documents := self add: MultipleSelectionListPresenter new
name:'documents'. <--STEP
        .....

in the next step the systems executates this method:

>>add: aPresenter name: aNameString
        "Adds aPresenter to the receiver's collection of sub-presenters and
        gives it aNameString. Answers aPresenter"

        aNameString first isUppercase ifTrue:[self halt].

        self subPresenters add: aPresenter.
        self name: aPresenter as: aNameString.
        aPresenter parentPresenter: self.
        ^aPresenter

My guess is that the system will not halt, but it does !!! inspecting
aNameString shows 'Documents'. No extra messages sends. I'm missing
something here? offcourse the consequences of this are that presenters
aren't connecting to views properly.

I'm using Dolphin PRO 5.1.4

By the way, I'm making a little framework that permits to presenters to
build context menues of it's subpresenters (only if specified) and
found this funny behavior.This are very useful when you have several
presenters with almost the same context menu (and common behavior).

Other thing I encountered that is rare was that executing in

Presenter>>onViewAvailable
        "A new view is available, but has not yet been connected to the
receiver, i.e.
        the view will not yet be aware of this presenter or its model.
        This is an appropriate point for subclasses to apply any dynamic view
        configuration that the application may require (e.g. setting a user
configured
        font previously saved in the Registry). Since the view is not yet
connected, any
        events fired will not reach this presenter or the model.
        This event is new for Dolphin 3.0"

        self createComponentContextMenues.

This #createComponentContextMenues methods should do nothing unless a
specification is found. I've implemented that with this:

Presenter>>createComponentContextMenues
        "Create the context menu for the presenters of the receiver.
        by default none context menu is added."

        "Filter to help developing."
        (self isKindOf: CustomerRequestPresenter) ifFalse:[^ nil].

        self subPresenters do:
                        [:presenter |
                        ((self hasContextMenuFor: presenter) and: [presenter view
contextMenu isNil])
                                ifTrue: [self addContextMenuTo: presenter]]


The line: "(self isKindOf: CustomerRequestPresenter) ifFalse:[^ nil]."
should not be necesary but if I remove it, then the system becomes
unable to open a class hierarchy browser. The strange thing is that
those are methods that I've added and they should be acting only in
(until now) only one presenter, so all other presenters should do
nothig. Any idea why the CHB could be breaking with this?

best regards,

Seb


Reply | Threaded
Open this post in threaded view
|

Re: string argument inexplicably modified

Bill Dargel
(Shortened the subject line, as I had trouble seeing all of it in my
news reader.
Was: "Very strange thing: a lowercase string is pased as argument to a
method with first letter in uppercase without anyone asking for it")

Sebastián wrote:
>  there is something really strange here. I'm watching with the debugger
> a method as the following:
>
> documents := self add: MultipleSelectionListPresenter new
> name:'documents'. <--STEP

My guess is that the literal string embedded in the method has been
modified. In D5 literal strings are not forced to be immutable. You can
check whether this is the case by inspecting the actual compiled method.

(CustomerRequestPresenter compiledMethodAt: #createComponents) inspect.

You could get into this situation by doing the equivalent of "aName at:
1 put: someUppercaseCharacter" somewhere in your code, which modified
the literal string, rather than a copy of it.

> Presenter>>onViewAvailable
> self createComponentContextMenues.

Instead, you should probably override just for your own subclass:

CustomerRequestPresenter>>onViewAvailable
        super onViewAvailable. "might not be strictly necessary here, but a
good habit when overriding framework messages"
  self createComponentContextMenues.

Then implement #createComponentContextMenues in
CustomerRequestPresenter, and the #isKindOf: test won't be necessary.

> Presenter>>createComponentContextMenues
> "Create the context menu for the presenters of the receiver.
> by default none context menu is added."
>
> "Filter to help developing."
> (self isKindOf: CustomerRequestPresenter) ifFalse:[^ nil].
>
> self subPresenters do:
> [:presenter |
> ((self hasContextMenuFor: presenter) and: [presenter view
> contextMenu isNil])
> ifTrue: [self addContextMenuTo: presenter]]


Any idea why the CHB could be breaking with this?

At least in my image, no one implements #hasContextMenuFor: or
#addContextMenuTo:, so unless you implement those to work for *all*
presenters, you don't want to change Presenter>>onViewAvailable such
that it depends on them. Can break all the views in the image, such as
the CHB.

--
Bill Dargel            [hidden email]
Shoshana Technologies
100 West Joy Road, Ann Arbor, MI 48105  USA


Reply | Threaded
Open this post in threaded view
|

Re: string argument inexplicably modified

Sebastián Sastre
Hi there,

 the "(CustomerRequestPresenter compiledMethodAt: #createComponents)
inspect" shows that the string is with its first letter in uppercase
just as the argument that goes in the next message.

 There is another sympthom I've found with this matter: it happends the
second time (and the sucesive ones) I instantiate the presenter. The
first time I open the main presenter everithing is OK, inspecting the
string shows it in lowercase. I dont know yet, but Is like if somewhere
the #names dictionary where modified after being connected.

regards,

Sebastián


Reply | Threaded
Open this post in threaded view
|

Re: string argument inexplicably modified

Sebastián Sastre
In reply to this post by Bill Dargel
>My guess is that the literal string embedded in the method has been
>modified. In D5 literal strings are not forced to be immutable. You can
>check whether this is the case by inspecting the actual compiled method.

Dear Bill, you absolutely right. Looking my code I've found this:

Presenter>>contextMenuDefinitionMethodSubfixFor: aPresenter

        "Private - Returns the string wich should be the subfix of the name of
the method that has a definition for a context menu of aPresenter."

        ^ 'Of', (self nameOf:aPresenter) asFirstUppercase

If you see the #asFirstUppercase method, you'll found that it in fact
modifies the literal bringing that unespected result. It only need to
be executed once and the compiled method becomes broken. I fixed it
with Presenter recompileAll.

thank you !

Sebastián


Reply | Threaded
Open this post in threaded view
|

Re: string argument inexplicably modified

Bill Dargel
Sebastián wrote:
> If you see the #asFirstUppercase method, you'll found that it in fact
> modifies the literal bringing that unespected result. It only need to
> be executed once and the compiled method becomes broken. I fixed it
> with Presenter recompileAll.

Not sure where you're getting #asFirstUppercase -- it's not in my image.
If you look at String>>capitalized, which comes with Dolphin, you'll see
that it makes a copy of the string. In general, it is good practice not
to modify the characters within a String object, unless you *know* that
no one else is holding onto it with the expectation that the value won't
change. So for example, if you've just made a copy of a it (like in
#capitalized), then it is safe to go changing the characters.

With the name #asFirstUppercase, starting with "as", my expectation is
that its a converting method, not a modifying method. That is,
converting one String object to another (leaving the initial receiver
unchanged). If the method is to actually change the String object, a
better name would be #changeFirstToUppercase.

>
> thank you !

You're welcome.

--
Bill Dargel            [hidden email]
Shoshana Technologies
100 West Joy Road, Ann Arbor, MI 48105  USA


Reply | Threaded
Open this post in threaded view
|

Re: string argument inexplicably modified

Sebastián Sastre
Bill,

  I was getting the #asFirstUppercase from my own code.I changed to
#capitalized now. I remember you that I'm making (already made
actually) a little framework to configure the context menues of
presenters (and it's subpresenters) programatically. This is a very
convenient (economic) strategy when you have lots of well refactored
presenters. I have rigth now 4 presenters with *almost* the same
context menu of about 10 commands. The differeces are specialized in
the ones who has the *diference* and I have potentially about 10
presenters *not yet developed* wich may be in a situation like that (at
least with their contexts and their common commands offcourse). So you
can make the numbers.

  About your comment of the name of #asFirstUppercase I totally agree.

  best regards,

Sebastián