Skip to content

[Refactorings] Fix for Negated condition violators#18597

Closed
carolahp wants to merge 8 commits intopharo-project:Pharo14from
carolahp:fix/violators-in-negated-conditions
Closed

[Refactorings] Fix for Negated condition violators#18597
carolahp wants to merge 8 commits intopharo-project:Pharo14from
carolahp:fix/violators-in-negated-conditions

Conversation

@carolahp
Copy link
Copy Markdown
Contributor

@carolahp carolahp commented Sep 25, 2025

Context

Condition violators are important for refactorings because they determine the actions taken by many drivers when breakingChangesPreconditions fail.
When violators are not accessible from drivers, they must replicate the logic behind preconditions to build descriptive error messages and implement the actions to handle possible failures.

Problem

Currently, violators are not valid for NegatedConditions. Consider the following code:
image

Solution

This PR is a proof of concept for a potential solution to this problem.
In this solution, a condition inside of a negation is aware of its corresponding negation condition, making it possible to delegate the result of the message violators to the negation when necessary.

The following code is an example, where the negation sets itself as the wrapper (wrapper is a bad name) of its condition and then tells it to print itself:
image

The condition delegates to the wrapper the responsibility to handle the return value of violators:
image

If the wrapper is nil, conditions return themselves, and therefore, they return violators in the traditional way:
image

But, if the wrapper is not nil (i.e. a negation), the violators message returns the condition's nonViolators:
image

Limitations

I am currently thinking of a more elegant solution because I don't like introducing an instance variable to Conditions

Therefore violationMessageOn: makes sense even if a condition is negated.
@balsa-sarenac
Copy link
Copy Markdown
Member

Hey @carolahp, this looks interesting. Thanks for looking into this issue!
I'd like to discuss this with you, we can do it tomorrow on the sync or after it.

I had some ideas, that I wanted to share. They go hand in hand with what you did, but some tweaks might be required. The core of it is: introduce nonViolators (which you already did!) which are basically set difference between violators and starting input. This will not be used by regular conditions, but only for negated condition. When you ask negated condition for violators, it returns nonViolators of its wrapped condition. When you have double wrapped negation, nonViolators form negation will give you violators form the wrapped condition, and we solve this issue. Now with this, only negation will be wrapper, regular preconditions will stay the same, which I think is important (not to complex them too much). However, there are some parts that will be interesting to implement, like: can we make nonViolators generic for all preconditions, or will every precondition need to define their own?
You can see how this is a modification of what you started here. I thought that I had already implemented it here, but haven't done do full work of migrating all preconditions to this new approach. Let me know what you think, or we can chat tomorrow.

@carolahp
Copy link
Copy Markdown
Contributor Author

carolahp commented Oct 9, 2025

Hi @balsa-sarenac thanks for your comments. You right about preventing nested wrappings of negations. To complement this idea and following what @Ducasse mentioned a few weeks ago, I made negated conditions return the condition when they receive the message not.
Regarding nonViolators I believe we could have a generic method and let subclasses redefine the set of potential violators (we may call them subjects. However, I am not sure if there would be a problem with complex conditions. Let's discuss it later in out sync.
I have updated the PR, getting I got rid of wrappers and implementing ReNewNegationCondition>>violationMessageOn: in a different way.
I will try to implement a generic version of nonViolators and see how it goes.

Comment on lines +4 to +6
#instVars : [
'wrapper'
],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this got left over, should be removed right?

Comment on lines 44 to 62
{ #category : 'displaying' }
ReNewNegationCondition >> violationMessageOn: aWriteStream [
| method re message message2 |
"If my condition is a negation, return its condition violation message"
condition class == self class
ifTrue: [ ^ condition condition violationMessageOn: aWriteStream ].

"Otherwise, send the method defined in the condition to self.
In this way, violators return nonViolators"
method := condition class lookupSelector: #violationMessageOn:.
message := String streamContents: [:s |
method valueWithReceiver: self arguments: { s }].

aWriteStream
nextPutAll: 'NOT ';
nextPutAll: condition errorString
"Remove 'not' apparitions from the message"
re := '[ ]+not[ ]*' asRegex.
message2 := re copy: message contents replacingMatchesWith: ' '.
message2 == message ifTrue: [ message2 := 'NOT ' + message ].
aWriteStream nextPutAll: message2
]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks better, we should discuss it today

@Ducasse
Copy link
Copy Markdown
Member

Ducasse commented Oct 16, 2025

@carolahp @balsa-sarenac is is ok to merge this one?

@carolahp
Copy link
Copy Markdown
Contributor Author

@carolahp @balsa-sarenac is is ok to merge this one?

Not yet @Ducasse , I am currently fixing the failing tests

@balsa-sarenac
Copy link
Copy Markdown
Member

@Ducasse I'll put Reviewed and ready to integrate label when it is ready

@carolahp
Copy link
Copy Markdown
Contributor Author

Replaced by #18738

@carolahp carolahp closed this Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants