Download the PHP package rasuvaeff/understudy-phpstan without Composer

On this page you can find all versions of the php package rasuvaeff/understudy-phpstan. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package understudy-phpstan

rasuvaeff/understudy-phpstan

Latest Stable Version Total Downloads Build Static analysis Psalm level PHP Русская версия

PHPStan extension for understudy.

Using an AI coding assistant? Point it at llms.txt.

Requirements

Installation

With phpstan/extension-installer that is all. Without it, include the extension yourself:

Usage

understudy specifies a call by making it inside a closure:

Four things about that line are invisible to PHPStan on its own, and this extension is those four things.

1. A matcher fits whatever the contract declares

Arg::int() is declared mixed, because a matcher has to be passable wherever a contract declares anything at all. At level 9 and above PHPStan reports it as Parameter #1 $id … expects int, mixed given — correct about the type, wrong about the code.

The extension types every matcher as never, the bottom type, which every parameter accepts. Nothing is suppressed. A wrong argument beside a matcher, a method the double does not have, the statements around the closure — all keep their reports:

Below level 9 there is nothing to fix here — PHPStan does not check mixed against a declared parameter — and the rest of the extension works at every level.

A specification is any of understudy's call-closure verbs, in either spelling: the free functions when(), expect(), expectSequence() and verify(), the same names on Understudy::, and the readers that exist only there — calls(), lastCall() and verifySequence(). Every closure of a protocol counts, so a matcher in the third step of an expectSequence() is read exactly like one in a when().

Two more idioms are covered the same way:

2. returns() is checked against the method being specified

The core declares when(): WhenBuilder<mixed>, and it has no choice: which method is being specified is known only from the closure. The extension fills the template parameter in, and PHPStan does the rest:

3. wire() has the shape of the class it wired

The shape says what the core builds, and only that. A parameter typed BookRepository&Auditor is ONE double standing for both contracts, so the key keeps the intersection and both halves stay callable. A parameter typed BookRepository|Clock makes the core refuse the class outright — CannotWire, because picking one of the two would be a guess — so no shape describes the call at all and the core's own array{sut: object, doubles: array<string, object>} stands. A dynamic class-string is left alone for the same reason.

4. Specifications that cannot work are reported

Each of these has a runtime counterpart — the engine throws, or the expectation never matches. Reporting them statically buys the one thing runtime cannot: a specification that can never match is exactly the mistake a green suite hides.

Identifier Reported when
understudy.closure The closure specifies nothing, makes more than one call, or calls a static method a double cannot intercept
understudy.cardinality times(5, 2), a negative bound, verify(…, never: true, times: 3), times beside a minimum
understudy.matcher A matcher whose kind the parameter can never accept: Arg::int() where a string is declared
understudy.returns returns() on a method declared void, where no value is ever observed
understudy.matcherLeak A matcher written outside a specification and outside a closure, where it reaches the code as a value. A matcher hoisted into a variable, stored on a property or written in a closure handed over later is not one: the closure has not run, and the specification that runs it is elsewhere

The rules are silent whenever they are not sure. A refined parameter type — non-empty-string, an int range — answers "maybe" to its plain kind, and a matcher can produce a value that fits it, so nothing is reported. A false accusation costs more than a missed one here, because the engine still catches at runtime what the extension misses.

To silence one of them, use its identifier:

Those identifiers are stable. They are what a consumer writes into their own phpstan.neon, and renaming one would silently stop an ignoreErrors entry somebody relies on; a new rule gets a new identifier rather than reusing an existing one. The wording of a message is not stable and a patch release may reword one — match on the identifier, never on the sentence.

Why understudy.matcherLeak exists

Typing every matcher as never is what lets one stand in for a typed parameter, and it does so everywhere — including in a real call:

Without a rule for it the extension would be weaker than no extension for that mistake, because PHPStan would otherwise have reported the argument itself. Saying it directly is also better than the type error it replaces: at runtime the matcher reaches the code as a sentinel object, and the failure it eventually causes names neither the matcher nor the line.

Security

The extension runs inside PHPStan, reads source and reflection, and reports. It executes no code from the project under analysis and writes nothing.

Examples

See examples/README.md. The executable demonstration is the set of fixture projects under tests/Integration/Fixtures, each analysed by a real PHPStan process as part of composer build — including a control run with the extension switched off, which is what tells a working extension apart from one that loads and does nothing.

The understudy family

Package What it is
rasuvaeff/understudy The engine: doubles, matchers, expectations, verification.
rasuvaeff/understudy-testo Testo adapter — verification and reset around every test.
rasuvaeff/understudy-phpunit PHPUnit and Pest adapter — the same, through a trait.
rasuvaeff/understudy-psalm Psalm plugin — matcher-aware specifications and misuse diagnostics.
rasuvaeff/understudy-phpstan (this package) PHPStan extension — the same for PHPStan, plus its own rules.

Development

License

BSD-3-Clause. See LICENSE.md.


All versions of understudy-phpstan with dependencies

PHP Build Version
Package Version
Requires php Version 8.3 - 8.5
nikic/php-parser Version ^5.0
phpstan/phpstan Version ^2.2.2
rasuvaeff/understudy Version ^0.8 || ^0.9
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package rasuvaeff/understudy-phpstan contains the following files

Loading the files please wait ...