pharo
pharo copied to clipboard
[RB]: whichSelectorsReferToClassVariable: does not work when a subclass accesses a class variable from the superclass
testWhichSelectorsReferToClassVariable
| root sub |
rbNamespace := RBNamespace onEnvironment: (RBClassEnvironment classes: {MyClassARoot . MySubAccessingSuperclassState }).
root := rbNamespace classNamed: #MyClassARoot.
sub := rbNamespace classNamed: #MySubAccessingSuperclassState.
self assert: (root whichSelectorsReferToClassVariable: #Shared1) isNotEmpty.
self assert: (sub whichSelectorsReferToClassVariable: #Shared1) isNotEmpty.
And now my code is
accessingSharedVariable
^ Shared1
So the variable is used.
To me
RBClass>>bindingOf: aString is wrong
bindingOf: aString
^self realClass classPool associationAt: aString asSymbol
ifAbsent: [self realClass classPool associationAt: aString asString ifAbsent: [nil]]
Because it does not look in the superclass. @MarcusDenker what do you think? I would delegate to the realClass in fact.
whichSelectorsReferToClassVariable: aString
| selectors |
selectors := Set new.
newMethods ifNotNil: [
newMethods do: [ :each |
(each refersToVariable: aString) ifTrue: [
selectors add: each selector ] ] ].
self isDefined ifTrue: [
selectors addAll:
(self existingMethodsThatReferToClassVariable: aString) ].
^ selectors
existingMethodsThatReferToClassVariable: aString
| binding existingMethods |
binding := (self bindingOf: aString)
ifNil: [ ^ #() ].
existingMethods := self realClass whichSelectorsReferTo: binding.
(newMethods isNil and: [ removedMethods isNil ])
ifTrue: [ ^ existingMethods ].
^ existingMethods
reject: [ :each | (self hasRemoved: each) or: [ self newMethods includesKey: each ] ]
Probably that the fix proposed for bindingOf: is fixing the problem here.
Yes, the current implementation of RBAbstractClass>>#bindingOf: is:
bindingOf: aString
^self realClass bindingOf: aString
Which will make this test green.
But: what is odd is that it goes directly to the main model. It means that if I would just add the class var and the method to the RB model (not to the main mode), it would return false. (the class "sub" on the RB level in the test has superclass Object)
To me it looks like we should implement bindingOf: in a way that it stays on the RB model, to take the data there into account only?