Skip to content
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

Subclass replacement operator #75

Merged
merged 24 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
19 changes: 11 additions & 8 deletions src/MuTalk-Model/MTBlockBasedMutantOperator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,40 @@ MTBlockBasedMutantOperator class >> isOriginalOperator [
^ false
]

{ #category : 'testing' }
{ #category : 'private' }
MTBlockBasedMutantOperator >> isAPosibleMutatedNode: aRBMethodNode [

| nodeThatMatches |
nodeThatMatches := aRBMethodNode allChildren detect: self newExpression ifNone: [nil].
^ nodeThatMatches notNil and: [
nodeThatMatches := aRBMethodNode allChildren
detect: self newExpression
ifNone: [ nil ].

^ nodeThatMatches notNil and: [
self is: nodeThatMatches equalTo: aRBMethodNode ]
]

{ #category : 'testing' }
{ #category : 'private' }
MTBlockBasedMutantOperator >> isAPosibleNodeToMutate: aRBMethodNode [

| nodeThatMatches |
nodeThatMatches := aRBMethodNode allChildren
detect: self expressionToReplace
ifNone: [ nil ].

^ nodeThatMatches notNil and: [
^ nodeThatMatches notNil and: [
self is: aRBMethodNode equalTo: nodeThatMatches ]
]

{ #category : 'private' }
MTBlockBasedMutantOperator >> modifiedSourceFor: aCompiledMethod with: aParseTree number: aNumber [
MTBlockBasedMutantOperator >> modifiedSourceFor: aCompiledMethod with: aParseTree number: aNumber newExpression: anExpression [

| parser allNodes |
parser := aParseTree copy.
allNodes := parser allChildren select: self expressionToReplace.
allNodes size >= aNumber ifTrue: [
allNodes size >= aNumber ifTrue: [
| oldNode newNode |
oldNode := allNodes at: aNumber.
newNode := self newExpression value: oldNode.
newNode := anExpression value: oldNode.
oldNode replaceWith: newNode ].
^ parser formattedCode
]
Expand Down
2 changes: 1 addition & 1 deletion src/MuTalk-Model/MTMessageSendToYourselfOperator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Class {
{ #category : 'printing' }
MTMessageSendToYourselfOperator >> description [

^ 'Chnage a message send with #yourself'
^ 'Change a message send with #yourself'
]

{ #category : 'applying' }
Expand Down
28 changes: 18 additions & 10 deletions src/MuTalk-Model/MTMethodMutation.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,23 @@ Class {
'operator',
'originalClass',
'testCaseReferences',
'originalProtocol'
'originalProtocol',
'newExpression'
],
#category : 'MuTalk-Model',
#package : 'MuTalk-Model'
}

{ #category : 'instance creation' }
MTMethodMutation class >> for: aMethod using: anOperatorApplied nodeNumber: aNodeNumber ofClass: aClass [
MTMethodMutation class >> for: aMethod using: anOperatorApplied nodeNumber: aNodeNumber ofClass: aClass replacingWith: anObject [

^ self new
initializeFor: aMethod
using: anOperatorApplied
nodeNumber: aNodeNumber
ofClass: aClass;
yourself
initializeFor: aMethod
using: anOperatorApplied
nodeNumber: aNodeNumber
ofClass: aClass
replacingWith: anObject;
yourself
]

{ #category : 'comparing' }
Expand All @@ -44,12 +47,14 @@ MTMethodMutation >> hash [
]

{ #category : 'initialize-release' }
MTMethodMutation >> initializeFor: aMethod using: anOperatorApplied nodeNumber: aNodeNumber ofClass: aClass [
MTMethodMutation >> initializeFor: aMethod using: anOperatorApplied nodeNumber: aNodeNumber ofClass: aClass replacingWith: anObject [

originalMethod := aMethod.
originalProtocol := aMethod protocol.
operator := anOperatorApplied.
nodeNumber := aNodeNumber.
originalClass := aClass
originalClass := aClass.
newExpression := anObject
]

{ #category : 'installing' }
Expand All @@ -64,7 +69,10 @@ MTMethodMutation >> install [
{ #category : 'accessing' }
MTMethodMutation >> modifiedSource [

^ operator modifiedSourceFor: originalMethod number: nodeNumber
^ operator
modifiedSourceFor: originalMethod
number: nodeNumber
newExpression: newExpression
]

{ #category : 'accessing' }
Expand Down
58 changes: 37 additions & 21 deletions src/MuTalk-Model/MTMutantOperator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -113,28 +113,32 @@ MTMutantOperator >> isNodeOfMutation: posibleMutatedRBMethodNode comparingWith:
]

{ #category : 'private' }
MTMutantOperator >> modifiedSourceFor: aCompiledMethod number: aNumber [
"this method must be removed, it is only added because some tests send this message - Gabo"
^self modifiedSourceFor: aCompiledMethod with: aCompiledMethod parseTree number: aNumber
MTMutantOperator >> modifiedSourceFor: aCompiledMethod number: aNumber newExpression: anExpression [

^ self
modifiedSourceFor: aCompiledMethod
with: aCompiledMethod parseTree
number: aNumber
newExpression: anExpression
]

{ #category : 'private' }
MTMutantOperator >> modifiedSourceFor: aCompiledMethod with: aParseTree number: aNumber [
MTMutantOperator >> modifiedSourceFor: aCompiledMethod with: aParseTree number: aNumber newExpression: anExpression [

| rewriter parser number nNode |
rewriter := RBParseTreeRewriter new.
number := aNumber.
parser := aParseTree copy.
rewriter
replace: self expressionToReplace
withValueFrom: [ :oNode |
withValueFrom: [ :oNode |
| oldNode newNode |
nNode := RBParser parseRewriteExpression: self newExpression.
nNode := RBParser parseRewriteExpression: anExpression.
nNode := nNode copyInContext: rewriter context.
oldNode := oNode.
newNode := nNode.
newNode ]
when: [ :node |
when: [ :node |
number := number - 1.
number = 0 ].
rewriter executeTree: parser.
Expand All @@ -143,13 +147,15 @@ MTMutantOperator >> modifiedSourceFor: aCompiledMethod with: aParseTree number:
]

{ #category : 'private' }
MTMutantOperator >> mutationFor: aCompiledMethod with: aParseTree number: aNumberOfSelector [
MTMutantOperator >> mutationFor: aCompiledMethod with: aParseTree number: aNumberOfSelector storeIn: aCollection [

^ MTMethodMutation
for: aCompiledMethod
using: self
nodeNumber: aNumberOfSelector
ofClass: aCompiledMethod methodClass
aCollection add: (MTMethodMutation
for: aCompiledMethod
using: self
nodeNumber: aNumberOfSelector
ofClass: aCompiledMethod methodClass
replacingWith: self newExpression).
^ aCollection
]

{ #category : 'mutant generation' }
Expand All @@ -162,16 +168,26 @@ MTMutantOperator >> mutationsFor: aCompiledMethod [
]

{ #category : 'mutant generation' }
MTMutantOperator >> mutationsFor: aCompiledMethod with: aParseTree [
MTMutantOperator >> mutationsFor: aCompiledMethod with: aParseTree [

| numberOfMutations |
numberOfMutations := ((aCompiledMethod hasPragmaNamed: #ignoreForMutations) or: [ aCompiledMethod hasPragmaNamed: #ignoreForCoverage ])
ifTrue: [ ^ Array new ]
ifFalse: [ self timesToApplyIn: aCompiledMethod with: aParseTree ].
numberOfMutations := ((aCompiledMethod hasPragmaNamed:
#ignoreForMutations) or: [
aCompiledMethod hasPragmaNamed:
#ignoreForCoverage ])
ifTrue: [ ^ Array new ]
ifFalse: [
self
timesToApplyIn: aCompiledMethod
with: aParseTree ].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh we are going to simplify this in our next pair programming session! ;)

^ (1 to: numberOfMutations)
collect: [:aNumberOfSelector | self
mutationFor: aCompiledMethod
with: aParseTree
number: aNumberOfSelector]
inject: OrderedCollection new
into: [ :collection :aNumberOfSelector |
self
mutationFor: aCompiledMethod
with: aParseTree
number: aNumberOfSelector
storeIn: collection ]
]

{ #category : 'applying' }
Expand Down
69 changes: 69 additions & 0 deletions src/MuTalk-Model/MTSubclassReplacementOperator.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Class {
#name : 'MTSubclassReplacementOperator',
#superclass : 'MTBlockBasedMutantOperator',
#instVars : [
'classesToReplace'
],
#category : 'MuTalk-Model-Operators',
#package : 'MuTalk-Model',
#tag : 'Operators'
}

{ #category : 'printing' }
MTSubclassReplacementOperator >> description [

^ 'Replace a class reference by a reference to one of its subclasses'
]

{ #category : 'applying' }
MTSubclassReplacementOperator >> expressionToReplace [

^ [ :aNode |
aNode isVariable and: [
(self class environment includesKey: aNode name) and: [
| referencedClass shouldReplace |
referencedClass := self class environment at: aNode name.
shouldReplace := referencedClass isClass and: [
referencedClass subclasses notEmpty ].
shouldReplace ifTrue: [ classesToReplace add: referencedClass ].
shouldReplace ] ] ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want that we discuss how to fix this. I know you just followed how others were done, but I don't like blocks used like this!

]

{ #category : 'initialization' }
MTSubclassReplacementOperator >> initialize [

super initialize.
classesToReplace := OrderedCollection new
]

{ #category : 'private' }
MTSubclassReplacementOperator >> mutationFor: aCompiledMethod with: aParseTree number: aNumberOfSelector storeIn: aCollection [

| classToReplace |
classToReplace := classesToReplace at: aNumberOfSelector.
aCollection addAll:
((1 to: classToReplace subclasses size) collect: [ :index |
| newExpression |
newExpression := self
newExpressionForClass: aNumberOfSelector
andSubclass: index.
MTMethodMutation
for: aCompiledMethod
using: self
nodeNumber: aNumberOfSelector
ofClass: aCompiledMethod methodClass
replacingWith: newExpression ]).
^ aCollection
]

{ #category : 'applying' }
MTSubclassReplacementOperator >> newExpressionForClass: classIndex andSubclass: subclassIndex [

^ [ :anOldNode |
| nodeCopy |
nodeCopy := anOldNode copy.
nodeCopy name:
((classesToReplace at: classIndex) subclasses at: subclassIndex)
name.
nodeCopy ]
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Class {
#name : 'MTAuxiliarClassForSubclassReplacementOperator',
#superclass : 'Object',
#category : 'MuTalk-TestResources',
#package : 'MuTalk-TestResources'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Class {
#name : 'MTAuxiliarClassForSubclassReplacementWithManySubclasses',
#superclass : 'Object',
#category : 'MuTalk-TestResources',
#package : 'MuTalk-TestResources'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Class {
#name : 'MTAuxiliarSubclass1ForSubclassReplacementWithManySubclasses',
#superclass : 'MTAuxiliarClassForSubclassReplacementWithManySubclasses',
#category : 'MuTalk-TestResources',
#package : 'MuTalk-TestResources'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Class {
#name : 'MTAuxiliarSubclass2ForSubclassReplacementWithManySubclasses',
#superclass : 'MTAuxiliarClassForSubclassReplacementWithManySubclasses',
#category : 'MuTalk-TestResources',
#package : 'MuTalk-TestResources'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Class {
#name : 'MTAuxiliarSubclass3ForSubclassReplacementWithManySubclasses',
#superclass : 'MTAuxiliarClassForSubclassReplacementWithManySubclasses',
#category : 'MuTalk-TestResources',
#package : 'MuTalk-TestResources'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Class {
#name : 'MTAuxiliarSubclassForSubclassReplacementOperator',
#superclass : 'MTAuxiliarClassForSubclassReplacementOperator',
#category : 'MuTalk-TestResources',
#package : 'MuTalk-TestResources'
}
Loading
Loading