Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6f74362
Adding the FamixDiff class, with getters and accessors
AntoninGoslin Apr 23, 2026
59db33c
Adding the contructor for the FamixDiff class
AntoninGoslin Apr 23, 2026
7993582
Adding printOn method to have a display like: FamixDiff(Addition -> E…
AntoninGoslin Apr 23, 2026
e596efc
Adding the test class of FamixDiff and a first test for the instance …
AntoninGoslin Apr 23, 2026
aa04f79
Update printOn in order to not have the name "Famix Diff" printed twice
AntoninGoslin Apr 23, 2026
c74afd1
Adding a difference list to collect all the differences.
AntoninGoslin Apr 23, 2026
0de73e1
Adding a method to add differences to the list of differences of Fami…
AntoninGoslin Apr 23, 2026
e072bdb
Updating the method compareEntity: to: ini order to have the differen…
AntoninGoslin Apr 23, 2026
f4178fe
FIX -> isEquals should start to true and not to false, tests are now OK
AntoninGoslin Apr 23, 2026
66d3694
Adding test cases -> with same classe, list of differences should be …
AntoninGoslin Apr 23, 2026
8599cce
Adding testing case -> two different typed entities should return a l…
AntoninGoslin Apr 23, 2026
3a95b27
Adding testing case -> two differents class should raison 1 differenc…
AntoninGoslin Apr 23, 2026
f77d631
FIX -> propertyChanged reason , not entity
AntoninGoslin Apr 23, 2026
a6c5531
Adding two test cases -> cases where we have the same classes, with s…
AntoninGoslin Apr 23, 2026
3acdf31
Adding a TODO task to see later how to correct this test
AntoninGoslin Apr 24, 2026
50147a1
Renaming test case for method additions when same class
AntoninGoslin Apr 24, 2026
2bbf334
Modify compareRelationTo -> adding the case of the differences betwee…
AntoninGoslin Apr 24, 2026
158f031
Adding deletion case in the method compareRelation from to, we now ha…
AntoninGoslin Apr 24, 2026
9411298
Adding addition case in the method compareRelation from to, we now ha…
AntoninGoslin Apr 24, 2026
6b59780
FIX -> missing return of isEqual boolean
AntoninGoslin Apr 24, 2026
f2b7ef4
FIX -> the test method need a root entity to be compared to other mod…
AntoninGoslin Apr 24, 2026
ba0ffe2
FIX -> copy paster error, we want to compare val2 for the addition ca…
AntoninGoslin Apr 24, 2026
75e78af
Adding test cases to test addition and deletion of entities
AntoninGoslin Apr 24, 2026
f136451
FIX -> switching the order of adding methods in the model
AntoninGoslin Apr 24, 2026
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
93 changes: 93 additions & 0 deletions Famix-Simple-Diff/FamixDiff.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
Class {
#name : 'FamixDiff',
#superclass : 'Object',
#instVars : [
'entity',
'changeType',
'expectedValue',
'actualValue'
],
#category : 'Famix-Simple-Diff',
#package : 'Famix-Simple-Diff'
}

{ #category : 'instance creation' }
FamixDiff class >> entity: anEntity changeType: aSymbol expectedValue: val1 actualValue: val2 [

| difference |
difference := FamixDiff new.
difference entity: anEntity.
difference changeType: aSymbol.
difference expectedValue: val1.
difference actualValue: val2.
^ difference
]

{ #category : 'accessing' }
FamixDiff >> actualValue [

^ actualValue
]

{ #category : 'accessing' }
FamixDiff >> actualValue: anObject [

actualValue := anObject
]

{ #category : 'accessing' }
FamixDiff >> changeType [

^ changeType
]

{ #category : 'accessing' }
FamixDiff >> changeType: anObject [

changeType := anObject
]

{ #category : 'accessing' }
FamixDiff >> entity [

^ entity
]

{ #category : 'accessing' }
FamixDiff >> entity: anObject [

entity := anObject
]

{ #category : 'accessing' }
FamixDiff >> expectedValue [

^ expectedValue
]

{ #category : 'accessing' }
FamixDiff >> expectedValue: anObject [

expectedValue := anObject
]

{ #category : 'printing' }
FamixDiff >> printOn: aStream [
"Redifine the display of the FamixDiff class"

"Will build a Stream like: FamixDiff(Addition -> Expected: ' ' | Actual: 'private int something' | On Class1)"

super printOn: aStream.
aStream nextPutAll: '('.
aStream print: changeType.

aStream
nextPutAll: ' -> Expected: ';
print: expectedValue;
nextPutAll: ' | Actual: ';
print: actualValue.

aStream nextPutAll: ' | On: '.
aStream print: entity.
aStream nextPutAll: ')'.
]
27 changes: 27 additions & 0 deletions Famix-Simple-Diff/FamixDiffTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Class {
#name : 'FamixDiffTest',
#superclass : 'TestCase',
#category : 'Famix-Simple-Diff',
#package : 'Famix-Simple-Diff'
}

{ #category : 'tests' }
FamixDiffTest >> testInstanceCreation [
| difference expectedValue actualValue |

"testing a code modification"
expectedValue := 'private int money;'.
actualValue := 'private int age;'.

difference := FamixDiff
entity: 'testEntity'
changeType: #entityModification
expectedValue: expectedValue
actualValue: actualValue.

"checking instance creation"
self assert: difference entity equals: 'testEntity'.
self assert: difference changeType equals: #entityModification.
self assert: difference expectedValue equals: expectedValue.
self assert: difference actualValue equals: actualValue.
]
139 changes: 122 additions & 17 deletions Famix-Simple-Diff/FamixSimpleDiff.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,70 @@ Class {
#instVars : [
'roots',
'childrenCache',
'debug'
'debug',
'differences'
],
#category : 'Famix-Simple-Diff',
#package : 'Famix-Simple-Diff'
}

{ #category : 'accessing' }
FamixSimpleDiff >> addDifference: aFamixDiff [
differences add: aFamixDiff
]

{ #category : 'comparing' }
FamixSimpleDiff >> compareEntity: aFamixEntity to: otherFamixEntity [

| properties relations |
aFamixEntity class = otherFamixEntity class ifFalse: [ ^ self fail ].
| properties relations diff isEquals |
isEquals := true.

"we compare the type of the entities. If we have not the same type, we add the difference in the list"
aFamixEntity class = otherFamixEntity class ifFalse: [
diff := (
FamixDiff
entity: otherFamixEntity
changeType: #entityChanged
expectedValue: aFamixEntity class name
actualValue: otherFamixEntity class name
).

self addDifference: diff.
^ self fail
].

"Comparing properties (slots with non-famix values)"
properties := aFamixEntity class allSlots select: [ :slot |
slot class = FMProperty ].
properties do: [ :p |
(p read: aFamixEntity) = (p read: otherFamixEntity) ifFalse: [
^ self fail ] ].
| prop1 prop2|
prop1 := p read: aFamixEntity.
prop2 := p read: otherFamixEntity.

diff := (
FamixDiff
entity: otherFamixEntity
changeType: #propertyChanged
expectedValue: prop1
actualValue: prop2
).
self addDifference: diff.
isEquals := false
]
].

"Comparing relations (slots with famix values)"
"We exclude source anchors because they are not relevant to model comparison"
relations := aFamixEntity class allSlots select: [ :slot |
slot isFMRelationSlot and: [ slot name ~= 'sourceAnchor' ] ].
relations do: [ :r |
(self compareRelation: r from: aFamixEntity to: otherFamixEntity)
ifFalse: [ ^ self fail ] ].
ifFalse: [ isEquals := false ] ].

"we stop the execution here if models are differents"
isEquals ifFalse: [ ^ self fail ].

"Every slot value is equal, the entities are identical"
^ true
]
Expand All @@ -52,16 +89,17 @@ FamixSimpleDiff >> compareModel: aFamixJavaModel to: aFamixJavaModel2 [
{ #category : 'comparing' }
FamixSimpleDiff >> compareRelation: aFMRelationSlot from: aFamixEntity to: otherFamixEntity [

| val1 val2 sortBlock |
| val1 val2 sortBlock isEquals diff|
isEquals := true.

aFMRelationSlot isToOne
ifTrue: [
val1 := aFMRelationSlot read: aFamixEntity.
val2 := aFMRelationSlot read: otherFamixEntity ]
ifFalse: [
| rejectBlock |
val1 := (aFMRelationSlot read: aFamixEntity) asOrderedCollection.
val2 := (aFMRelationSlot read: otherFamixEntity)
asOrderedCollection.
val2 := (aFMRelationSlot read: otherFamixEntity)asOrderedCollection.

sortBlock := val1
ifEmpty: [ self sortBlock ]
Expand All @@ -80,19 +118,80 @@ FamixSimpleDiff >> compareRelation: aFMRelationSlot from: aFamixEntity to: other
val1 == val2 ifTrue: [ ^ true ].

aFMRelationSlot isToOne
ifTrue: [ ^ (self pathesForMaybeMultiRelation: val1) = (self pathesForMaybeMultiRelation: val2) ]
ifFalse: [ "This is a toMany Relation! and the value should be a collection"
val1 size = val2 size ifFalse: [ ^ self fail ].
val1 := val1
ifTrue: [
| areSame |
"if we dont have the same relations, so it changed, we have to record it"
areSame := (self pathesForMaybeMultiRelation: val1) = (self pathesForMaybeMultiRelation: val2).
areSame ifFalse: [
diff := (
FamixDiff
entity: otherFamixEntity
changeType: #relationChanged
expectedValue: val1
actualValue: val2
).
self addDifference: diff.
isEquals := false.
]
]

"This is a toMany Relation! and the value should be a collection"
ifFalse: [

"if we have different sizes of val, here we have an addition or a deletion"
"val1 size = val2 size ifFalse: [ ^ self fail ]."

| expectedBag actualBag|
expectedBag := val1
flatCollect: [ :e | self pathesForMaybeMultiRelation: e ]
as: Bag.
val2 := val2
actualBag := val2
flatCollect: [ :e | self pathesForMaybeMultiRelation: e ]
as: Bag.

val1 = val2
ifFalse: [ ^ self fail ]
ifTrue: [ ^ true ] ]
"compute additions and deletion between bags"
expectedBag = actualBag ifFalse: [
isEquals := false.

"deletion case, here in the model 1, but not in model 2"
val1 do:[ :expectedEntity |
| path allInBag|
"check the path of the expected entity, if all the paths are not in the expectedBag, so we have a deletion"
path := self pathesForMaybeMultiRelation: expectedEntity.
allInBag := (path allSatisfy: [ :p | actualBag includes: p]).
allInBag ifFalse: [
diff := (
FamixDiff
entity: otherFamixEntity
changeType: #entityRemoved
expectedValue: expectedEntity
actualValue: nil
).
self addDifference: diff.
].
].

"addition case, not here in the model 1, but here in the model 2"
val2 do:[ :actualEntity |
| path allInBag|
"check the path of the actual entity, if all the paths are not in the actual, so we have a addition"
path := self pathesForMaybeMultiRelation: actualEntity .
allInBag := (path allSatisfy: [ :p | expectedBag includes: p]).
allInBag ifFalse: [
diff := (
FamixDiff
entity: otherFamixEntity
changeType: #entityAdded
expectedValue: nil
actualValue: actualEntity
).
self addDifference: diff.
].
].
].
].

^ isEquals.
]

{ #category : 'path-computing' }
Expand Down Expand Up @@ -127,6 +226,11 @@ FamixSimpleDiff >> debugOn [
debug := true
]

{ #category : 'accessing' }
FamixSimpleDiff >> differences [
^ differences
]

{ #category : 'path-computing' }
FamixSimpleDiff >> entityAtPath: indexPath fromEntity: entity [

Expand Down Expand Up @@ -178,7 +282,8 @@ FamixSimpleDiff >> initialize [

super initialize.
debug := false.
childrenCache := LRUCache new maximumWeight: 100
childrenCache := LRUCache new maximumWeight: 100.
differences := OrderedCollection new.
]

{ #category : 'path-computing' }
Expand Down
Loading