pharo-project / pharo

Pharo is a dynamic reflective pure object-oriented language supporting live programming inspired by Smalltalk.
http://pharo.org
Other
1.21k stars 356 forks source link

ComputedSlot is missing accessor #block #17070

Closed jvalteren closed 2 months ago

jvalteren commented 2 months ago

While working with my own ReadAccessorSlot (a subclass of ComputedSlot), I ran into the following error: ReadAccessorSlot(Object)>>doesNotUnderstand: #block. See full stack trace below for completeness.

I discovered that ComputedSlot implements #hasSameDefinitionAs:, in which it sends #block to otherSlot, but the class doesn't actually implement this accessor.

I will create a pull request with the missing accessor method.

Stack trace

ReadAccessorSlot(Object)>>doesNotUnderstand: #block
ReadAccessorSlot(ComputedSlot)>>hasSameDefinitionAs:
[ :aVar :bVar |
            (aVar hasSameDefinitionAs: bVar) ifFalse: [ ^ false ] ] in ShSlotChangeDetector(ShAbstractClassChangeDetector)>>compareVariables:with: in Block: [ :aVar :bVar |...
OrderedCollection(SequenceableCollection)>>with:do:
ShSlotChangeDetector(ShAbstractClassChangeDetector)>>compareVariables:with:
[ :a :b | self compareVariables: a with: b ] in ShSlotChangeDetector>>initialize in Block: [ :a :b | self compareVariables: a with: b ]
ShSlotChangeDetector(ShAbstractClassChangeDetector)>>compareClass
ShSlotChangeDetector class(ShAbstractChangeDetector class)>>compareClass:with:
[ :e | e compareClass: oldClass with: self ] in ShiftClassBuilder>>compareWithOldClass in Block: [ :e | e compareClass: oldClass with: self ]
OrderedCollection>>do:
ShiftClassBuilder>>compareWithOldClass
ShiftClassBuilder>>build
[
        newClass := builder build.

        self installInEnvironment: newClass.

        self installSubclassInSuperclass: newClass.

        builder builderEnhancer beforeMigratingClass: builder installer: self.

        builder builderEnhancer migrateToClass: newClass installer: self.

        builder builderEnhancer afterMigratingClass: builder installer: self.

        builder builderEnhancer propagateChangesToRelatedClasses: newClass builder: builder.

    ] in ShiftClassInstaller>>make in Block: [...
FullBlockClosure(BlockClosure)>>on:do:
ShiftClassInstaller>>make
ShiftClassInstaller>>makeWithBuilder:
ShiftClassBuilder>>install
ShiftClassBuilder>>fluidInstall
ClySystemEnvironment>>compileANewClassFrom:notifying:startingFrom:
ClyFullBrowserMorph>>compileANewClassFrom:notifying:startingFrom:
ClyClassDefinitionEditorToolMorph>>applyChangesAsClassDefinition
ClyClassDefinitionEditorToolMorph>>applyChanges
[
          self changesAreAboutApply.
          applied := self applyChanges ] in [
          textMorph hasUnacceptedEdits: true.
          [
          self changesAreAboutApply.
          applied := self applyChanges ]
              on: Error
              do: [ :err |
                  textModel setText: self editingText.
                  textMorph hasUnacceptedEdits: true.
                  err pass ].

          applied
              ifTrue: [
                  textModel setText: self editingText.
                  textMorph hasUnacceptedEdits: false.
                  self textUpdated.
                  browser focusActiveTab ]
              ifFalse: [ textMorph hasUnacceptedEdits: true ] ] in ClyClassDefinitionEditorToolMorph(ClyTextEditorToolMorph)>>changesAccepted in Block: [...
FullBlockClosure(BlockClosure)>>on:do:
[
          textMorph hasUnacceptedEdits: true.
          [
          self changesAreAboutApply.
          applied := self applyChanges ]
              on: Error
              do: [ :err |
                  textModel setText: self editingText.
                  textMorph hasUnacceptedEdits: true.
                  err pass ].

          applied
              ifTrue: [
                  textModel setText: self editingText.
                  textMorph hasUnacceptedEdits: false.
                  self textUpdated.
                  browser focusActiveTab ]
              ifFalse: [ textMorph hasUnacceptedEdits: true ] ] in ClyClassDefinitionEditorToolMorph(ClyTextEditorToolMorph)>>changesAccepted in Block: [...
FullBlockClosure(BlockClosure)>>ensure:
ClyClassDefinitionEditorToolMorph(ClyTextEditorToolMorph)>>applyChangesBy:
ClyClassDefinitionEditorToolMorph(ClyTextEditorToolMorph)>>changesAccepted
MessageSend>>value
MessageSend>>cull:
MessageSend>>cull:cull:
[ action cull: anAnnouncement cull: announcer ] in AnnouncementSubscription(AbstractAnnouncementSubscription)>>deliver: in Block: [ action cull: anAnnouncement cull: announcer ]
FullBlockClosure(BlockClosure)>>on:do:
[ Processor terminateRealActive ] in [ :ex |
              | onDoCtx handler bottom thisCtx |
              onDoCtx := thisContext.
              thisCtx := onDoCtx home.

              "find the context on stack for which this method's is sender"

              [ onDoCtx sender == thisCtx ] whileFalse: [
                  onDoCtx := onDoCtx sender.
                  onDoCtx ifNil: [ "Can't find our home context. seems like we're already forked
                and handling another exception in new thread. In this case, just pass it through handler."
                      ^ handlerAction cull: ex ] ].

              bottom := [ Processor terminateRealActive ] asContext.
              onDoCtx privSender: bottom.

              handler := [ handlerAction cull: ex ] asContext.
              handler privSender: thisContext sender.

              (Process forContext: handler priority: Processor activePriority) resume.

              "cut the stack of current process"
              thisContext privSender: thisCtx.
              nil ] in FullBlockClosure(BlockClosure)>>on:fork: in Block: [ Processor terminateRealActive ]
Ducasse commented 2 months ago

Thanks for the report. We will have a look

MarcusDenker commented 2 months ago

Thanks, I merged the PR