functional-php icon indicating copy to clipboard operation
functional-php copied to clipboard

Support psalm

Open lstrojny opened this issue 6 years ago • 10 comments

Add psalm annotations

  • [ ] Fix all issues found by psalm
  • [x] Increase type specificity
  • [x] Add @psalm-pure
  • [x] Add @psalm-assert
  • [ ] Add proper support for more complex cases like compose

Type specificity

  • [x] Average
  • [x] ButLast
  • [x] Capture
  • [x] CompareObjectHashOn
  • [x] CompareOn
  • [x] Compose
  • [x] Concat
  • [x] ConstFunction
  • [x] Contains
  • [x] Converge
  • [ ] Curry
  • [ ] CurryN
  • [x] Difference
  • [x] DropFirst
  • [x] DropLast
  • [x] Each
  • [x] Equal
  • [x] ErrorToException
  • [x] Every
  • [x] Exceptions/InvalidArgumentException
  • [x] Exceptions/MatchException
  • [x] False
  • [x] Falsy
  • [x] Filter
  • [x] First
  • [x] FirstIndexOf
  • [x] FlatMap
  • [x] Flatten
  • [x] Flip
  • [x] Functional
  • [x] GreaterThan
  • [x] GreaterThanOrEqual
  • [x] Group
  • [x] Head
  • [x] Id
  • [x] Identical
  • [x] IfElse
  • [x] IndexesOf
  • [x] Intersperse
  • [x] Invoke
  • [x] InvokeFirst
  • [x] InvokeIf
  • [x] InvokeLast
  • [x] Invoker
  • [x] Last
  • [x] LastIndexOf
  • [x] LessThan
  • [x] LessThanOrEqual
  • [x] LexicographicCompare
  • [x] Map
  • [x] Match
  • [x] Maximum
  • [x] Memoize
  • [x] Minimum
  • [x] None
  • [x] Noop
  • [x] Not
  • [x] OmitKeys
  • [x] PartialAny
  • [x] PartialLeft
  • [x] PartialMethod
  • [x] PartialRight
  • [x] Partition
  • [x] Pick
  • [x] Pluck
  • [x] Poll
  • [x] Product
  • [x] Ratio
  • [x] ReduceLeft
  • [x] ReduceRight
  • [x] Reindex
  • [x] Reject
  • [x] Repeat
  • [x] Retry
  • [x] Select
  • [x] SelectKeys
  • [x] SequenceConstant
  • [x] SequenceExponential
  • [x] SequenceLinear
  • [x] Sequences/ExponentialSequence
  • [x] Sequences/LinearSequence
  • [x] Some
  • [x] Sort
  • [x] Sum
  • [x] SuppressError
  • [x] Tail
  • [x] TailRecursion
  • [x] TakeLeft
  • [x] TakeRight
  • [x] Tap
  • [x] True
  • [x] Truthy
  • [x] Unique
  • [ ] With
  • [ ] Zip
  • [ ] ZipAll

Issues

  • invoker(), invoke(), partial_method(): no way to annotate method names properly: https://github.com/vimeo/psalm/issues/2500
  • Recursive types are not implemented (problem for compose, curry, etc.): https://github.com/vimeo/psalm/issues/2499

lstrojny avatar Dec 19 '19 16:12 lstrojny

Nice to see that you decided to go with Psalm! I think this is the best choice for a lib like yours, where templates and @psalm- specific annotations can really help end users.

I would like to help with the integration, if you don't mind (and if it's really needed...). Can start from the end of the list, to not mess with you.

alexeyshockov avatar Dec 20 '19 06:12 alexeyshockov

@lstrojny, please take a look at #209

alexeyshockov avatar Dec 20 '19 12:12 alexeyshockov

@alexeyshockov it would be terrific to collaborate on this topic. I've just pushed my current WIP, would you mind rebasing. Unfortunately it’s going to create a few conflicts, sorry about that. How about we agree to mark an item before working on it, so we avoid duplicate work?

lstrojny avatar Dec 20 '19 16:12 lstrojny

@ondrejmirtes Could @phpstan 0.12 also benefit from this work to make this available to even broader user base?

jkuchar avatar Jan 02 '20 11:01 jkuchar

@jkuchar PHPStan can benefit from generics annotations, not from "pure" or "assert" yet. Instead of assert annotations, right now a TypeSpecifyingExtension has to be written. There are already extensions like that for PHPUnit, for beberlei/assert and webmozart/assert.

Of course, an extension like this can be written to interpret these phpDoc annotations but no one did that yet.

ondrejmirtes avatar Jan 02 '20 11:01 ondrejmirtes

One little thing to add: comment of variable length argument need a fix

It should be mixed ...$arguments. Otherwise, psalm always reports an error.

InvalidArgument - src/test.php:151:56 - Argument 2 of Functional\partial_right expects array<array-key, mixed>, string(BASE) provided

foalford avatar Jan 22 '20 08:01 foalford

Hi @lstrojny! Since 3.11.3 Psalm supports func_num_args() for conditional types. You could use for compose but with compromises.

/**
 * @template A
 * @template B
 * @template C
 * @template D
 * @template F
 * @template G
 * @template H
 * @template I
 *
 * @param callable(A):B $aToB
 * @param callable(B):C $bToC
 * @param callable(C):D $cToD
 * @param callable(D):F $dToF
 * @param callable(F):G $fToG
 * @param callable(G):H $gToH
 * @param callable(H):I $hToI
 *
 * @return (func_num_args() is 2 ? callable(A):C : (
 *          func_num_args() is 3 ? callable(A):D : (
 *          func_num_args() is 4 ? callable(A):F : (
 *          func_num_args() is 5 ? callable(A):G : (
 *          func_num_args() is 6 ? callable(A):H : (
 *          func_num_args() is 7 ? callable(A):I : callable
 *         ))))))
 */
function compose(
    callable $aToB,
    callable $bToC,
    callable $cToD = null,
    callable $dToF = null,
    callable $fToG = null,
    callable $gToH = null,
    callable $hToI = null,
    callable ...$others
) {
    // impl here
}

In this case you can type limited arguments count. After the limit compose will return just callable.

Unfortunately you can pass null value instead of one of callable.

A similar solution used by rxjs

Inference example: image

Error example: image

klimick avatar Jun 28 '20 19:06 klimick

@klimick that’s a great idea, thank you!

lstrojny avatar Jun 30 '20 13:06 lstrojny

Isn't this ready to be merged? (even incomplete) :-)

jkuchar avatar Dec 21 '20 14:12 jkuchar

Hey, for anyone interested in psalm/phpstan support, there is an alternative to this library that has generics: azjezz/psl.

  • https://github.com/azjezz/psl/blob/2.1.x/docs/component/vec.md
  • https://github.com/azjezz/psl/blob/2.1.x/docs/component/dict.md

adrienbrault avatar Sep 30 '22 15:09 adrienbrault