pharo icon indicating copy to clipboard operation
pharo copied to clipboard

[RB]: whichSelectorsReferToClassVariable: does not work when a subclass accesses a class variable from the superclass

Open Ducasse opened this issue 2 years ago • 5 comments

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.
	


Ducasse avatar Oct 07 '23 14:10 Ducasse

And now my code is

accessingSharedVariable

	^ Shared1 

So the variable is used.

Ducasse avatar Oct 07 '23 14:10 Ducasse

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.

Ducasse avatar Oct 07 '23 14:10 Ducasse

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 ] ]

Ducasse avatar Oct 07 '23 14:10 Ducasse

Probably that the fix proposed for bindingOf: is fixing the problem here.

Ducasse avatar Oct 07 '23 16:10 Ducasse

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?

MarcusDenker avatar Oct 10 '23 08:10 MarcusDenker