Skip to content

Commit

Permalink
Merge pull request #3906 from VincentBlondeau/FIX/Backportof#3410
Browse files Browse the repository at this point in the history
[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
  • Loading branch information
MarcusDenker authored Jul 19, 2019
2 parents 591a635 + 0829363 commit b8c5878
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 6 deletions.
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

0 comments on commit b8c5878

Please sign in to comment.