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

Add Intervals class to allow checking for subsets and intersections between constraints #97

Merged
merged 28 commits into from
May 19, 2020

Conversation

Seldaek
Copy link
Member

@Seldaek Seldaek commented May 5, 2020

No description provided.

src/Constraint/Constraint.php Outdated Show resolved Hide resolved
src/Constraint/Constraint.php Outdated Show resolved Hide resolved
src/Constraint/MultiConstraint.php Outdated Show resolved Hide resolved
src/Constraint/MultiConstraint.php Outdated Show resolved Hide resolved
tests/IntervalsTest.php Outdated Show resolved Hide resolved
src/Intervals.php Outdated Show resolved Hide resolved
src/Intervals.php Outdated Show resolved Hide resolved
@Seldaek Seldaek force-pushed the subsets branch 2 times, most recently from b82b8e4 to b894127 Compare May 8, 2020 08:07
@Seldaek
Copy link
Member Author

Seldaek commented May 8, 2020

Ok all tests passing except one now, which is technically a valid result but not really what I'd like it to return.. @Toflar if you'd like to try and use this latest version in your Composer PR feel free.

@Seldaek
Copy link
Member Author

Seldaek commented May 8, 2020

All tests now passing.

5aef5c2 adds a new isIntersectionOf method which could theoretically replace ConstraintInterface::matches() but I doubt it's as efficient so maybe not. We need to test and see. Anyway it was a great experiment as it allowed me to fix a few more edge cases in the intervals generation.

@naderman would be happy to get your opinion on 67b8bb5 and 0b0edb3 especially

src/Intervals.php Outdated Show resolved Hide resolved
@Seldaek Seldaek changed the title Add basic tests and implementation for isSubsetOf Add Intervals class to allow checking for subsets and intersections between constraints May 19, 2020
@Seldaek Seldaek marked this pull request as ready for review May 19, 2020 08:32

// filter out invalid intervals like > x - <= x, or >= x - < x
if (
version_compare($intervals[$index]['start']->getVersion(), $border['version'], '=')
Copy link
Member

Choose a reason for hiding this comment

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

Is it necessary to use version_compare even with normalized versions for equality?

Copy link
Member Author

Choose a reason for hiding this comment

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

With normalized constraints no it is not needed I believe. We do have some tests using non-normalized constraints, and technically nothing preventing you from creating Constraint instances with non-normalized versions. I don't know if we want to just document this as "voiding warranty" and drop the version_compare for perf, or keep supporting these edge cases.

Copy link
Member Author

Choose a reason for hiding this comment

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

BTW the failing tests that triggered me to add this were https://github.com/composer/semver/blob/master/tests/Constraint/ConstraintTest.php#L494 where b2 and beta2 do not compare equally without version_compare. Constraint::matches uses version_compare so technically it is supported to some extent, even though in Composer we never create non-normalized constraints AFAIK.

@naderman
Copy link
Member

I still think it'd be better to have an actual Interval class rather than these arrays with start/end attributes which essentially act like an untyped object.

break 2;
}
// != dev-foo || == dev-master -> != dev-foo
if ($op === '==') {
Copy link
Member

Choose a reason for hiding this comment

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

this behaves incorrectly for anyDev, e.g. != dev-foo || == dev* -> * not != dev-foo

Copy link
Member

Choose a reason for hiding this comment

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

Should probably also add a test that covers this situation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in 3d72ad3

src/Intervals.php Outdated Show resolved Hide resolved
src/Intervals.php Outdated Show resolved Hide resolved
@Seldaek
Copy link
Member Author

Seldaek commented May 19, 2020

Fixed all feedback.

*/
private static function generateIntervals(ConstraintInterface $constraint, $stopOnFirstValidInterval = false)
{
if ($constraint instanceof EmptyConstraint) {
return array('intervals' => array(array('start' => self::zero(), 'end' => self::positiveInfinity())), 'devConstraints' => array(self::anyDev()));
return array('intervals' => array(new Interval(Interval::zero(), Interval::positiveInfinity())), 'devConstraints' => array(Interval::anyDev()));
Copy link
Contributor

Choose a reason for hiding this comment

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

Imho we have the same optimization possibility here as we'd have with a ConstraintFactory: we don't need a new instance of Interval over and over again if the interval is exactly the same. We could reuse existing interval instances, right? :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, but IMO that's still best done with the memoization on get(), because the expensive stuff here is computing intervals for a constraint, not storing them. Especially as they'll get used at poolbuilder time and then it can be cleared as it becomes useless. Feel free to PR if you have time though :P

@naderman naderman merged commit e639bd3 into composer:master May 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants