Skip to content

[Backport] Fix for #3410-[Trait] Impossible to use from a classTrait a method that is also defined in a subclass of Behavior even when following the doc #3906

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
Class {
#name : #T2OverloadingOfMethodsInTraitedClassTest,
#superclass : #T2AbstractTest,
#category : #'TraitsV2-Tests-Tests'
}

{ #category : #tests }
T2OverloadingOfMethodsInTraitedClassTest >> createT1 [
| t1 |
t1 := self newTrait: #T1 with: '' asSlotCollection.
t1 classTrait
compile:
'isTrueForUsersOfTheTraitForT2OverloadingOfMethodsInTraitedClassTest
"Should be removed at the end of the test"
^true
'.
TraitedClass
compile:
'isTrueForUsersOfTheTraitForT2OverloadingOfMethodsInTraitedClassTest
"Should be removed at the end of the test"
^false
'.
Behavior
compile:
'isTrueForUsersOfTheTraitForT2OverloadingOfMethodsInTraitedClassTest
"Should be removed at the end of the test"
^false
'.
^ t1
]

{ #category : #tests }
T2OverloadingOfMethodsInTraitedClassTest >> createT2 [
^ self newTrait: #T2 with: '' asSlotCollection
]

{ #category : #running }
T2OverloadingOfMethodsInTraitedClassTest >> tearDown [
TraitedClass
removeSelector: #isTrueForUsersOfTheTraitForT2OverloadingOfMethodsInTraitedClassTest.
Behavior
removeSelector: #isTrueForUsersOfTheTraitForT2OverloadingOfMethodsInTraitedClassTest.
super tearDown
]

{ #category : #tests }
T2OverloadingOfMethodsInTraitedClassTest >> testDirectTraitSubclassing [
| t1 c1 |
t1 := self createT1.
c1 := self newClass: #C1 with: '' asSlotCollection uses: t1.
self
assert:
c1 isTrueForUsersOfTheTraitForT2OverloadingOfMethodsInTraitedClassTest
]

{ #category : #tests }
T2OverloadingOfMethodsInTraitedClassTest >> testIndirectTraitSubclassing [
| t1 t2 superclass subclass |
t1 := self createT1.
t2 := self createT2.
superclass := self
newClass: #C2Superclass
with: '' asSlotCollection
uses: t2.

subclass := self
newClass: #C1Subclass
superclass: superclass
with: '' asSlotCollection
uses: t1.
self
deny:
superclass
isTrueForUsersOfTheTraitForT2OverloadingOfMethodsInTraitedClassTest.
self
assert:
subclass
isTrueForUsersOfTheTraitForT2OverloadingOfMethodsInTraitedClassTest
]
12 changes: 10 additions & 2 deletions src/TraitsV2/TaClassCompositionElement.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@ Class {
{ #category : #accessing }
TaClassCompositionElement >> methods [
"As I am representing a ClassTrait I have to filter the methods that are in all the class traits"
^ super methods reject: [ :e | TraitedClass selectors anySatisfy: [ :x | x = e selector ] ]
| innerClassLocalMethods |
innerClassLocalMethods := innerClass localMethods collect: #selector.
^ super methods reject: [ :e | (innerClassLocalMethods includes: e selector) not and: [TraitedClass selectors anySatisfy: [ :x | x = e selector ]] ]
]

{ #category : #accessing }
TaClassCompositionElement >> selectors [
"As I am representing a ClassTrait I have to filter the methods that are in all the class traits"
^ super selectors reject: [ :e | TraitedClass selectors includes: e ]

| innerClassLocalMethods |
innerClassLocalMethods := innerClass localMethods collect: #selector.
^ super selectors
reject: [ :e |
(innerClassLocalMethods includes: e) not
and: [ TraitedClass selectors includes: e ] ]
]

{ #category : #accessing }
Expand Down
12 changes: 8 additions & 4 deletions src/TraitsV2/TraitedMetaclass.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -210,22 +210,26 @@ TraitedMetaclass >> isRejectedMethod: aSelector [
"The method is not installed in method dictionary if:
- It is in the localMethods.
- It is from Class (we already have them) and they are not overriden in TraitedClass.
- If it is in TraitedClass and it is in my superclass.
- If it is in TraitedClass and it is in my superclass (except if the trait I used defines the selector myself).
"

| isFromClass isFromTraitedClass isMySuperclassTraitedClass |
| isFromClass isFromTraitedClass isMySuperclassTraitedClass isTheTraitIUseDefinesTheSelector |
(self isLocalSelector: aSelector)
ifTrue: [ ^ true ].

isFromClass := Class canUnderstand: aSelector.
isFromTraitedClass := TraitedClass methodDict includesKey: aSelector.
isMySuperclassTraitedClass := (superclass isKindOf: TraitedMetaclass) and: [superclass isObsolete not].



(isFromClass and: [ isFromTraitedClass not ])
ifTrue: [ ^ true ].

(isFromTraitedClass and: isMySuperclassTraitedClass)
ifTrue: [ ^ true ].
ifTrue: [
isTheTraitIUseDefinesTheSelector := self traitComposition traits anySatisfy: [:inTrait | inTrait localMethods anySatisfy: [ :meth | meth selector = aSelector ]].
isTheTraitIUseDefinesTheSelector ifTrue:[ ^false ].
^ true ].

^ false
]
Expand Down