[
  {
    "path": ".gitattributes",
    "content": "logo export-ignore\ntests export-ignore\n.gitignore export-ignore\n.gitattributes export-ignore\n.travis.yml export-ignore\ncomposer-require-checker.json export-ignore\nexport-ignore export-ignore\nphpcs.xml.dist export-ignore\nphpstan.neon.dist export-ignore\nphpunit.xml.dist export-ignore\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "tidelift: \"packagist/roave/no-floaters\"\n"
  },
  {
    "path": ".github/workflows/continuous-integration.yml",
    "content": "# See https://github.com/laminas/laminas-continuous-integration-action\n# Generates a job matrix based on current dependencies and supported version\n# ranges, then runs all those jobs\nname: \"Continuous Integration\"\n\non:\n  pull_request:\n  push:\n\njobs:\n  matrix:\n    name: Generate job matrix\n    runs-on: ubuntu-latest\n    outputs:\n      matrix: ${{ steps.matrix.outputs.matrix }}\n    steps:\n      - name: Gather CI configuration\n        id: matrix\n        uses: laminas/laminas-ci-matrix-action@1.33.0\n\n  qa:\n    name: QA Checks\n    needs: [ matrix ]\n    runs-on: ${{ matrix.operatingSystem }}\n    strategy:\n      fail-fast: false\n      matrix: ${{ fromJSON(needs.matrix.outputs.matrix) }}\n    steps:\n      - name: ${{ matrix.name }}\n        uses: laminas/laminas-continuous-integration-action@1.43.0\n        env:\n          \"GITHUB_TOKEN\": ${{ secrets.GITHUB_TOKEN }}\n          \"INFECTION_DASHBOARD_API_KEY\": ${{ secrets.INFECTION_DASHBOARD_API_KEY }}\n          \"STRYKER_DASHBOARD_API_KEY\": ${{ secrets.STRYKER_DASHBOARD_API_KEY }}\n        with:\n          job: ${{ matrix.job }}\n"
  },
  {
    "path": ".github/workflows/release-on-milestone-closed.yml",
    "content": "# https://help.github.com/en/categories/automating-your-workflow-with-github-actions\n\nname: \"Automatic Releases\"\n\non:\n  milestone:\n    types:\n      - \"closed\"\n\njobs:\n  release:\n    name: \"GIT tag, release & create merge-up PR\"\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: \"Checkout\"\n        uses: \"actions/checkout@v6\"\n\n      - name: \"Release\"\n        uses: \"laminas/automatic-releases@v1\"\n        with:\n          command-name: \"laminas:automatic-releases:release\"\n        env:\n          \"GITHUB_TOKEN\": ${{ secrets.GITHUB_TOKEN }}\n          \"SIGNING_SECRET_KEY\": ${{ secrets.SIGNING_SECRET_KEY }}\n          \"GIT_AUTHOR_NAME\": ${{ secrets.GIT_AUTHOR_NAME }}\n          \"GIT_AUTHOR_EMAIL\": ${{ secrets.GIT_AUTHOR_EMAIL }}\n\n      - name: \"Create Merge-Up Pull Request\"\n        uses: \"laminas/automatic-releases@v1\"\n        with:\n          command-name: \"laminas:automatic-releases:create-merge-up-pull-request\"\n        env:\n          \"GITHUB_TOKEN\": ${{ secrets.GITHUB_TOKEN }}\n          \"SIGNING_SECRET_KEY\": ${{ secrets.SIGNING_SECRET_KEY }}\n          \"GIT_AUTHOR_NAME\": ${{ secrets.GIT_AUTHOR_NAME }}\n          \"GIT_AUTHOR_EMAIL\": ${{ secrets.GIT_AUTHOR_EMAIL }}\n\n      - name: \"Create and/or Switch to new Release Branch\"\n        uses: \"laminas/automatic-releases@v1\"\n        with:\n          command-name: \"laminas:automatic-releases:switch-default-branch-to-next-minor\"\n        env:\n          \"GITHUB_TOKEN\": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}\n          \"SIGNING_SECRET_KEY\": ${{ secrets.SIGNING_SECRET_KEY }}\n          \"GIT_AUTHOR_NAME\": ${{ secrets.GIT_AUTHOR_NAME }}\n          \"GIT_AUTHOR_EMAIL\": ${{ secrets.GIT_AUTHOR_EMAIL }}\n\n      - name: \"Bump Changelog Version On Originating Release Branch\"\n        uses: \"laminas/automatic-releases@v1\"\n        with:\n          command-name: \"laminas:automatic-releases:bump-changelog\"\n        env:\n          \"GITHUB_TOKEN\": ${{ secrets.GITHUB_TOKEN }}\n          \"SIGNING_SECRET_KEY\": ${{ secrets.SIGNING_SECRET_KEY }}\n          \"GIT_AUTHOR_NAME\": ${{ secrets.GIT_AUTHOR_NAME }}\n          \"GIT_AUTHOR_EMAIL\": ${{ secrets.GIT_AUTHOR_EMAIL }}\n\n      - name: \"Create new milestones\"\n        uses: \"laminas/automatic-releases@v1\"\n        with:\n          command-name: \"laminas:automatic-releases:create-milestones\"\n        env:\n          \"GITHUB_TOKEN\": ${{ secrets.GITHUB_TOKEN }}\n          \"SIGNING_SECRET_KEY\": ${{ secrets.SIGNING_SECRET_KEY }}\n          \"GIT_AUTHOR_NAME\": ${{ secrets.GIT_AUTHOR_NAME }}\n          \"GIT_AUTHOR_EMAIL\": ${{ secrets.GIT_AUTHOR_EMAIL }}\n"
  },
  {
    "path": ".gitignore",
    "content": "/vendor\n.phpunit.cache\n.phpunit.result.cache"
  },
  {
    "path": ".laminas-ci.json",
    "content": "{\n  \"extensions\": [\n    \"pcov\"\n  ],\n  \"exclude\": [\n    {\"name\": \"Infection\"}\n  ],\n  \"additional_checks\": [\n    {\n      \"name\": \"Infection (PCOV)\",\n      \"job\": {\n        \"php\": \"@lowest\",\n        \"dependencies\": \"locked\",\n        \"command\": \"./vendor/bin/roave-infection-static-analysis-plugin\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Roave, LLC\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# roave/no-floaters\n\n![`roave/no-floaters`](logo/roave-no-floaters.png)\n\n[![Latest Stable Version](https://poser.pugx.org/roave/no-floaters/v/stable.png)](https://packagist.org/packages/roave/no-floaters)\n\nThis library is a [PHPStan](https://github.com/phpstan/phpstan) plugin\nthat disallows:\n\n* declaration of `float` properties\n* `float` method parameters\n* `float` method return types\n* assignment of `float` values to variables or properties\n\nThe reason for this restriction is that rounding errors coming\nfrom floating point arithmetic operations are not acceptable in\ncertain business logic scenario, such as dealing with money,\nevaluating exam results, rocket science, etc.\n\nAn example of such problems can be seen with the following typical\n[example](https://3v4l.org/MJqJe):\n\n```php\nvar_dump((0.7 + 0.1) === 0.8); // output: bool(false)\n```\n\nThis can mean no trouble at all, or a lot of trouble, depending\non how many numbers you are running through your system, so it\nis advisable to avoid `float` for domains where rounding can\npotentially lead to trouble.\n\n`float` is still perfectly acceptable in many programming contexts,\nand this ruleset should only be applied where it is critical not\nto introduce rounding errors.\n\n## Installation\n\n```sh\ncomposer require --dev roave/no-floaters\n```\n\n## Configuration\n\nIn your `phpstan.neon` configuration, add following section:\n\n```neon\nincludes:\n    - vendor/roave/no-floaters/rules.neon\n```\n\nOptionally, you can configure the library to disallow any\n`float`-producing expression at all, by adding following to your\n`phpstan.neon`:\n\n```neon\nparameters:\n    disallowFloatsEverywhere: true\n```\n\nIf the above is enabled, given the following `example-file.php`\ncontents:\n\n```php\n<?php\n\n$a = 1 / 3;\n```\n\nYou should get something like following:\n\n```cli\nvendor/bin/phpstan analyse example-file.php -l 7\n 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%\n\n ------ -----------------------------------------------------\n  Line   example-file.php\n ------ -----------------------------------------------------\n  3      Cannot assign float to $a - floats are not allowed.\n ------ -----------------------------------------------------\n\n\n [ERROR] Found 1 error\n\n```\n\n## roave/no-floaters for enterprise\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of roave/no-floaters and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-roave-no-floaters?utm_source=packagist-roave-no-floaters&utm_medium=referral&utm_campaign=enterprise&utm_term=repo).\n\nIf you need help with setting up this library in your project,\nyou can contact us at <team@roave.com> for consulting/support.\n"
  },
  {
    "path": "SECURITY.md",
    "content": "## Security contact information\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure.\n"
  },
  {
    "path": "composer-require-checker.json",
    "content": "{\n    \"symbol-whitelist\": [\n        \"null\",\n        \"true\",\n        \"false\",\n        \"static\",\n        \"self\",\n        \"parent\",\n        \"array\",\n        \"string\",\n        \"int\",\n        \"float\",\n        \"bool\",\n        \"iterable\",\n        \"callable\",\n        \"void\",\n        \"object\",\n        \"PHPStan\\\\Analyser\\\\Scope\",\n        \"PHPStan\\\\Node\\\\Printer\\\\Printer\",\n        \"PHPStan\\\\Reflection\\\\FunctionReflection\",\n        \"PHPStan\\\\Reflection\\\\MethodReflection\",\n        \"PHPStan\\\\Reflection\\\\ParametersAcceptor\",\n        \"PHPStan\\\\Reflection\\\\ReflectionProvider\",\n        \"PHPStan\\\\Rules\\\\Rule\",\n        \"PHPStan\\\\Rules\\\\RuleErrorBuilder\",\n        \"PHPStan\\\\ShouldNotHappenException\",\n        \"PHPStan\\\\Type\\\\FloatType\",\n        \"PHPStan\\\\Type\\\\LateResolvableType\",\n        \"PHPStan\\\\Type\\\\MixedType\",\n        \"PHPStan\\\\Type\\\\NeverType\",\n        \"PHPStan\\\\Type\\\\Type\",\n        \"PHPStan\\\\Type\\\\VerbosityLevel\"\n    ],\n    \"php-core-extensions\": [\n        \"Core\",\n        \"date\",\n        \"pcre\",\n        \"Reflection\",\n        \"SPL\",\n        \"standard\",\n        \"mbstring\"\n    ]\n}\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"roave/no-floaters\",\n    \"type\": \"phpstan-extension\",\n    \"description\": \"PHPStan Rules to Disallow Float proliferation in contexts where IEEE-754 rounding errors are not acceptable\",\n    \"license\": [\n        \"MIT\"\n    ],\n    \"require\": {\n        \"php\": \"~8.3.0 || ~8.4.0 || ~8.5.0\",\n        \"nikic/php-parser\": \"^5.7.0\",\n        \"phpstan/phpstan\": \"^2.1.39\"\n    },\n    \"require-dev\": {\n        \"doctrine/coding-standard\": \"^14.0.0\",\n        \"maglnet/composer-require-checker\": \"^4.20.0\",\n        \"phpstan/phpstan-phpunit\": \"^2.0.16\",\n        \"phpstan/phpstan-strict-rules\": \"^2.0.10\",\n        \"phpunit/phpunit\": \"^12.5.11\",\n        \"psalm/plugin-phpunit\": \"^0.19.5\",\n        \"roave/infection-static-analysis-plugin\": \"^1.43.0\",\n        \"squizlabs/php_codesniffer\": \"^4.0.1\",\n        \"vimeo/psalm\": \"^6.15.1\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Roave\\\\PHPStan\\\\Rules\\\\Floats\\\\\": \"src/\"\n        }\n    },\n    \"autoload-dev\": {\n        \"classmap\": [\n            \"tests/asset\"\n        ],\n        \"psr-4\": {\n            \"Roave\\\\PHPStanTest\\\\Rules\\\\Floats\\\\\": \"tests/src\"\n        }\n    },\n    \"config\": {\n        \"allow-plugins\": {\n            \"infection/extension-installer\": false,\n            \"dealerdirect/phpcodesniffer-composer-installer\": true\n        },\n        \"platform\": {\n            \"php\": \"8.3.99\"\n        },\n        \"sort-packages\": true\n    }\n}\n"
  },
  {
    "path": "infection.json.dist",
    "content": "{\n    \"$schema\": \"vendor/infection/infection/resources/schema.json\",\n    \"source\": {\n        \"directories\": [\n            \"src\"\n        ]\n    },\n    \"logs\": {\n        \"text\": \"php://stderr\",\n        \"github\": true\n    },\n    \"mutators\": {\n        \"@default\": true\n    },\n    \"minMsi\": 100,\n    \"minCoveredMsi\": 100\n}"
  },
  {
    "path": "phpcs.xml.dist",
    "content": "<?xml version=\"1.0\"?>\n<ruleset\n    name=\"PHPStan Disallow Float Rules\"\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:noNamespaceSchemaLocation=\"vendor/squizlabs/php_codesniffer/phpcs.xsd\"\n>\n    <rule ref=\"Doctrine\">\n        <exclude name=\"Generic.Files.LineLength.TooLong\"/>\n    </rule>\n\n    <file>src</file>\n    <file>tests/src</file>\n</ruleset>\n"
  },
  {
    "path": "phpstan.neon.dist",
    "content": "includes:\n\t- vendor/phpstan/phpstan-phpunit/extension.neon\n\t- vendor/phpstan/phpstan-phpunit/rules.neon\n\t- vendor/phpstan/phpstan-strict-rules/rules.neon\n\t- rules.neon\n\nparameters:\n\tpaths:\n\t\t- %currentWorkingDirectory%/src\n\t\t- %currentWorkingDirectory%/tests/src\n\tlevel: 8\n\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit\n        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n        xsi:noNamespaceSchemaLocation=\"./vendor/phpunit/phpunit/phpunit.xsd\"\n        colors=\"true\"\n        failOnAllIssues=\"true\"\n        beStrictAboutChangesToGlobalState=\"true\"\n        beStrictAboutOutputDuringTests=\"true\"\n        beStrictAboutCoverageMetadata=\"true\"\n        cacheDirectory=\".phpunit.cache\">\n  <testsuites>\n    <testsuite name=\"PHPStan Disallow Float Test Suite\">\n      <directory>./tests/src</directory>\n    </testsuite>\n  </testsuites>\n  <coverage ignoreDeprecatedCodeUnits=\"true\" disableCodeCoverageIgnore=\"true\"/>\n  <source>\n    <include>\n      <directory suffix=\".php\">src</directory>\n    </include>\n  </source>\n</phpunit>\n"
  },
  {
    "path": "psalm.xml",
    "content": "<?xml version=\"1.0\"?>\n<psalm\n    errorLevel=\"1\"\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xmlns=\"https://getpsalm.org/schema/config\"\n    xsi:schemaLocation=\"https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd\"\n>\n    <plugins>\n        <pluginClass class=\"Psalm\\PhpUnitPlugin\\Plugin\"/>\n    </plugins>\n\n    <projectFiles>\n        <directory name=\"src\" />\n        <directory name=\"tests\" />\n        <ignoreFiles>\n            <directory name=\"vendor\" />\n            <directory name=\"tests/asset\" />\n        </ignoreFiles>\n    </projectFiles>\n    \n    <issueHandlers>\n        <MissingOverrideAttribute errorLevel=\"suppress\">\n            <!-- the #[Override] attribute is mostly useless -->\n        </MissingOverrideAttribute>\n        <PossiblyUnusedReturnValue>\n            <errorLevel type=\"suppress\">\n                <!-- these files are visitors, and their return values are only used by the\\\n                     visitor implementation in PHPStan itself -->\n                <file name=\"src/DisallowFloatInMethodSignatureRule.php\"/>\n                <file name=\"src/DisallowFloatPropertyTypeRule.php\"/>\n            </errorLevel>\n        </PossiblyUnusedReturnValue>\n    </issueHandlers>\n</psalm>\n"
  },
  {
    "path": "renovate.json",
    "content": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\n    \"local>Ocramius/.github:renovate-config\"\n  ]\n}\n"
  },
  {
    "path": "rules.neon",
    "content": "rules:\n\t- Roave\\PHPStan\\Rules\\Floats\\DisallowFloatAssignedToVariableRule\n\t- Roave\\PHPStan\\Rules\\Floats\\DisallowFloatInFunctionSignatureRule\n\t- Roave\\PHPStan\\Rules\\Floats\\DisallowFloatInMethodSignatureRule\n\t- Roave\\PHPStan\\Rules\\Floats\\DisallowFloatPropertyTypeRule\n\nparameters:\n\tdisallowFloatsEverywhere: false\n\nconditionalTags:\n\tRoave\\PHPStan\\Rules\\Floats\\DisallowFloatEverywhereRule:\n\t\tphpstan.rules.rule: %disallowFloatsEverywhere%\n\nservices:\n\t-\n\t\tclass: Roave\\PHPStan\\Rules\\Floats\\DisallowFloatEverywhereRule\n\nparametersSchema:\n\tdisallowFloatsEverywhere: bool()\n"
  },
  {
    "path": "src/DisallowFloatAssignedToVariableRule.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStan\\Rules\\Floats;\n\nuse PhpParser\\Node;\nuse PHPStan\\Analyser\\Scope;\nuse PHPStan\\Node\\Printer\\Printer;\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\Rules\\RuleErrorBuilder;\nuse PHPStan\\Type\\VerbosityLevel;\n\nuse function sprintf;\n\n/** @implements Rule<Node> */\nfinal class DisallowFloatAssignedToVariableRule implements Rule\n{\n    public function __construct(private Printer $printer)\n    {\n    }\n\n    public function getNodeType(): string\n    {\n        return Node::class;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function processNode(Node $node, Scope $scope): array\n    {\n        if (! $node instanceof Node\\Expr\\AssignOp && ! $node instanceof Node\\Expr\\Assign) {\n            return [];\n        }\n\n        $resultType = $scope->getType($node);\n        if (! FloatTypeHelper::isFloat($resultType)) {\n            return [];\n        }\n\n        return [\n            RuleErrorBuilder::message(sprintf(\n                'Cannot assign %s to %s - floats are not allowed.',\n                $resultType->describe(VerbosityLevel::typeOnly()),\n                $this->printer->prettyPrintExpr($node->var),\n            ))->identifier('float.assign')->build(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/DisallowFloatEverywhereRule.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStan\\Rules\\Floats;\n\nuse PhpParser\\Node;\nuse PhpParser\\Node\\Expr;\nuse PHPStan\\Analyser\\Scope;\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\Rules\\RuleErrorBuilder;\nuse PHPStan\\Type\\VerbosityLevel;\n\nuse function sprintf;\n\n/**\n * @implements Rule<Expr>\n * @final not designed for inheritance, but kept open for BC, until the next major release\n */\nclass DisallowFloatEverywhereRule implements Rule\n{\n    public function getNodeType(): string\n    {\n        return Expr::class;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function processNode(Node $node, Scope $scope): array\n    {\n        if (\n            $node instanceof Node\\Expr\\AssignOp\n            || $node instanceof Node\\Expr\\Assign\n        ) {\n            return [];\n        }\n\n        $nodeType = $scope->getType($node);\n        if (! FloatTypeHelper::isFloat($nodeType)) {\n            return [];\n        }\n\n        return [\n            RuleErrorBuilder::message(sprintf(\n                'Cannot have %s as a result type of this expression - floats are not allowed.',\n                $nodeType->describe(VerbosityLevel::typeOnly()),\n            ))->identifier('float.expression')->build(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/DisallowFloatInFunctionSignatureRule.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStan\\Rules\\Floats;\n\nuse PhpParser\\Node;\nuse PhpParser\\Node\\Name;\nuse PhpParser\\Node\\Stmt\\Function_;\nuse PHPStan\\Analyser\\Scope;\nuse PHPStan\\Reflection\\FunctionReflection;\nuse PHPStan\\Reflection\\ParameterReflection;\nuse PHPStan\\Reflection\\ParametersAcceptor;\nuse PHPStan\\Reflection\\ReflectionProvider;\nuse PHPStan\\Rules\\IdentifierRuleError;\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\Rules\\RuleError;\nuse PHPStan\\Rules\\RuleErrorBuilder;\nuse PHPStan\\Type\\VerbosityLevel;\n\nuse function array_filter;\nuse function array_keys;\nuse function array_map;\nuse function array_merge;\nuse function array_values;\nuse function sprintf;\n\n/** @implements Rule<Function_> */\nfinal class DisallowFloatInFunctionSignatureRule implements Rule\n{\n    public function __construct(private ReflectionProvider $reflectionProvider)\n    {\n    }\n\n    public function getNodeType(): string\n    {\n        return Function_::class;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function processNode(Node $node, Scope $scope): array\n    {\n        $functionName = new Name($node->name->toString());\n        if (! $this->reflectionProvider->hasFunction($functionName, $scope)) {\n            return [];\n        }\n\n        $functionReflection = $this->reflectionProvider->getFunction($functionName, $scope);\n\n        $errors = [];\n\n        foreach ($functionReflection->getVariants() as $functionVariant) {\n            $errors[] = $this->violationsForParameters($functionVariant, $functionReflection);\n            $errors[] = $this->returnTypeViolations($functionVariant, $functionReflection);\n        }\n\n        return array_merge([], ...$errors);\n    }\n\n    /** @return list<IdentifierRuleError> */\n    private function returnTypeViolations(\n        ParametersAcceptor $function,\n        FunctionReflection $functionReflection,\n    ): array {\n        if (! FloatTypeHelper::isFloat($function->getReturnType())) {\n            return [];\n        }\n\n        return [\n            RuleErrorBuilder::message(sprintf(\n                'Function %s() cannot have %s as its return type - floats are not allowed.',\n                $functionReflection->getName(),\n                $function->getReturnType()->describe(VerbosityLevel::typeOnly()),\n            ))->identifier('float.function')->build(),\n        ];\n    }\n\n    /** @return list<IdentifierRuleError> */\n    private function violationsForParameters(\n        ParametersAcceptor $function,\n        FunctionReflection $functionReflection,\n    ): array {\n        $parameters = $function->getParameters();\n\n        return array_values(array_filter(array_map(\n            static function (ParameterReflection $parameter, int $index) use ($functionReflection): RuleError|null {\n                if (! FloatTypeHelper::isFloat($parameter->getType())) {\n                    return null;\n                }\n\n                return RuleErrorBuilder::message(sprintf(\n                    'Parameter #%d $%s of function %s() cannot have %s as its type - floats are not allowed.',\n                    $index + 1,\n                    $parameter->getName(),\n                    $functionReflection->getName(),\n                    $parameter->getType()->describe(VerbosityLevel::typeOnly()),\n                ))->identifier('float.function')->build();\n            },\n            $parameters,\n            array_keys($parameters),\n        ), static fn (RuleError|null $error): bool => $error !== null));\n    }\n}\n"
  },
  {
    "path": "src/DisallowFloatInMethodSignatureRule.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStan\\Rules\\Floats;\n\nuse PhpParser\\Node;\nuse PhpParser\\Node\\Stmt\\ClassMethod;\nuse PHPStan\\Analyser\\Scope;\nuse PHPStan\\Reflection\\ClassReflection;\nuse PHPStan\\Reflection\\MethodReflection;\nuse PHPStan\\Reflection\\ParameterReflection;\nuse PHPStan\\Reflection\\ParametersAcceptor;\nuse PHPStan\\Rules\\IdentifierRuleError;\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\Rules\\RuleError;\nuse PHPStan\\Rules\\RuleErrorBuilder;\nuse PHPStan\\ShouldNotHappenException;\nuse PHPStan\\Type\\VerbosityLevel;\n\nuse function array_filter;\nuse function array_keys;\nuse function array_map;\nuse function array_merge;\nuse function array_values;\nuse function sprintf;\n\n/** @implements Rule<ClassMethod> */\nfinal class DisallowFloatInMethodSignatureRule implements Rule\n{\n    public function getNodeType(): string\n    {\n        return ClassMethod::class;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function processNode(Node $node, Scope $scope): array\n    {\n        if (! $scope->isInClass()) {\n            throw new ShouldNotHappenException();\n        }\n\n        /** @psalm-var ClassReflection $classReflection */\n        $classReflection = $scope->getClassReflection();\n        $methodName      = $node->name->toString();\n        $method          = $classReflection->getNativeMethod($methodName);\n\n        $errors = [];\n\n        foreach ($method->getVariants() as $methodVariant) {\n            $errors[] = $this->violationsForParameters($methodVariant, $method);\n            $errors[] = $this->returnTypeViolations($methodVariant, $method);\n        }\n\n        return array_merge([], ...$errors);\n    }\n\n    /** @return list<IdentifierRuleError> */\n    private function returnTypeViolations(\n        ParametersAcceptor $method,\n        MethodReflection $methodReflection,\n    ): array {\n        if (! FloatTypeHelper::isFloat($method->getReturnType())) {\n            return [];\n        }\n\n        return [\n            RuleErrorBuilder::message(sprintf(\n                'Method %s::%s() cannot have %s as its return type - floats are not allowed.',\n                $methodReflection->getDeclaringClass()->getDisplayName(),\n                $methodReflection->getName(),\n                $method->getReturnType()->describe(VerbosityLevel::typeOnly()),\n            ))->identifier('float.type')->build(),\n        ];\n    }\n\n    /** @return list<IdentifierRuleError> */\n    private function violationsForParameters(\n        ParametersAcceptor $function,\n        MethodReflection $methodReflection,\n    ): array {\n        $parameters = $function->getParameters();\n\n        return array_values(array_filter(array_map(\n            static function (ParameterReflection $parameter, int $index) use ($methodReflection): RuleError|null {\n                if (! FloatTypeHelper::isFloat($parameter->getType())) {\n                    return null;\n                }\n\n                return RuleErrorBuilder::message(sprintf(\n                    'Parameter #%d $%s of method %s::%s() cannot have %s as its type - floats are not allowed.',\n                    $index + 1,\n                    $parameter->getName(),\n                    $methodReflection->getDeclaringClass()->getDisplayName(),\n                    $methodReflection->getName(),\n                    $parameter->getType()->describe(VerbosityLevel::typeOnly()),\n                ))->identifier('float.type')->build();\n            },\n            $parameters,\n            array_keys($parameters),\n        ), static fn (RuleError|null $error): bool => $error !== null));\n    }\n}\n"
  },
  {
    "path": "src/DisallowFloatPropertyTypeRule.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStan\\Rules\\Floats;\n\nuse PhpParser\\Node;\nuse PhpParser\\Node\\PropertyItem;\nuse PHPStan\\Analyser\\Scope;\nuse PHPStan\\Reflection\\ClassReflection;\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\Rules\\RuleErrorBuilder;\nuse PHPStan\\ShouldNotHappenException;\nuse PHPStan\\Type\\VerbosityLevel;\n\nuse function sprintf;\n\n/** @implements Rule<PropertyItem> */\nfinal class DisallowFloatPropertyTypeRule implements Rule\n{\n    public function getNodeType(): string\n    {\n        return PropertyItem::class;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function processNode(Node $node, Scope $scope): array\n    {\n        if (! $scope->isInClass()) {\n            throw new ShouldNotHappenException();\n        }\n\n        /** @psalm-var ClassReflection $classReflection */\n        $classReflection = $scope->getClassReflection();\n        $propertyName    = $node->name->toString();\n        $property        = $classReflection->getNativeProperty($node->name->toString());\n        $propertyType    = $property->getReadableType();\n        if (! FloatTypeHelper::isFloat($propertyType)) {\n            return [];\n        }\n\n        return [\n            RuleErrorBuilder::message(sprintf(\n                'Property %s::$%s cannot have %s as its type - floats are not allowed.',\n                $property->getDeclaringClass()->getDisplayName(),\n                $propertyName,\n                $propertyType->describe(VerbosityLevel::typeOnly()),\n            ))->identifier('float.property')->build(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/FloatTypeHelper.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStan\\Rules\\Floats;\n\nuse PHPStan\\Type\\FloatType;\nuse PHPStan\\Type\\LateResolvableType;\nuse PHPStan\\Type\\MixedType;\nuse PHPStan\\Type\\NeverType;\nuse PHPStan\\Type\\Type;\n\n/** @internal class is only for internal tooling use: do not import it in your own projects */\nfinal class FloatTypeHelper\n{\n    public static function isFloat(Type $type): bool\n    {\n        if ($type instanceof MixedType) {\n            return false;\n        }\n\n        if ($type instanceof NeverType) {\n            return false;\n        }\n\n        if ($type instanceof LateResolvableType) {\n            return self::isFloat($type->resolve());\n        }\n\n        return ! (new FloatType())->isSuperTypeOf($type)->no();\n    }\n}\n"
  },
  {
    "path": "tests/asset/assign.php",
    "content": "<?php\n\nnamespace DisallowFloatsInAssign;\n\nclass Foo\n{\n\n    private $foo;\n\n    private $bar;\n\n    /**\n     * @param float $float\n     * @param int|float $intOrFloat\n     */\n    public function doFoo($float, $intOrFloat, string $str)\n    {\n        $test = $float;\n        $test2 = $intOrFloat;\n\n        $this->foo = $float;\n        $this->bar['test'] = $float;\n\n        $test3 = $str;\n    }\n\n    public function doBar()\n    {\n        $test = 0;\n        $test += 1;\n        $test += 3.14;\n    }\n\n}\n"
  },
  {
    "path": "tests/asset/expr.php",
    "content": "<?php\n\nnamespace DisallowFloatsEverywhere;\n\nfunction () {\n    $foo = 1.3;\n    $foo += 1.3;\n\n    foo(\n        3.14\n    );\n};\n"
  },
  {
    "path": "tests/asset/function.php",
    "content": "<?php\n\nnamespace DisallowFloatsInFunctionSignatures;\n\n/**\n * @param float $float\n * @param int|float $intOrFloat\n * @param string $string\n * @return float\n */\nfunction doFoo(\n    float $float,\n    $intOrFloat,\n    string $string,\n    $mixed\n): float\n{\n\n}\n\nfunction doBar(): string\n{\n\n}\n\n/**\n * @return never\n */\nfunction withNever()\n{\n    throw new \\RuntimeException();\n}\n"
  },
  {
    "path": "tests/asset/functionNotAutoloaded.php",
    "content": "<?php\n\nfunction nonexistentRoaveFunction(): float\n{\n\n}\n"
  },
  {
    "path": "tests/asset/functionWithInterpolatedFloatAndNonFloatParameters.php",
    "content": "<?php\n\nnamespace DisallowFloatsInFunctionSignatures;\n\n/** @param mixed $d */\nfunction functionWithInterpolatedFloatAndNonFloatParameters(\n    float $a,\n    string $b,\n    float $c,\n    $d,\n    float $e\n) {\n\n}\n"
  },
  {
    "path": "tests/asset/functionWithoutNamespace.php",
    "content": "<?php\n\n/**\n * @param float $float\n * @param int|float $intOrFloat\n * @param string $string\n * @return float\n */\nfunction doFoo(\n    float $float,\n    $intOrFloat,\n    string $string,\n    $mixed\n): float\n{\n\n}\n\nfunction doBar(): string\n{\n\n}\n"
  },
  {
    "path": "tests/asset/method.php",
    "content": "<?php\n\nnamespace DisallowFloatsInMethodSignatures;\n\nclass Foo\n{\n\n    /**\n     * @param float $float\n     * @param int|float $intOrFloat\n     * @param string $string\n     * @return float\n     */\n    public function doFoo(\n        float $float,\n        $intOrFloat,\n        string $string,\n        $mixed\n    ): float\n    {\n\n    }\n\n    public function doBar(): string\n    {\n\n    }\n\n    /**\n     * @return never\n     */\n    public function withNever()\n    {\n        throw new \\RuntimeException();\n    }\n}\n"
  },
  {
    "path": "tests/asset/methodWithConditionalReturnType.php",
    "content": "<?php\n\nnamespace DisallowFloatsInMethodSignatures;\n\nuse Exception;\n\nuse function gettype;\n\n/**\n * @template TObject of object\n */\ninterface DenormalizerInterface\n{\n    /**\n     * @param class-string<TObject>|string $type\n     * @return ($type is class-string<TObject> ? TObject : mixed)\n     */\n    public function denormalize(mixed $data, string $type): mixed;\n}\n\nclass Denormalizer implements DenormalizerInterface\n{\n    public function denormalize(mixed $data, string $type): mixed\n    {\n        return new \\stdClass();\n    }\n}\n\nclass DummyTypeConverter {\n    /**\n     * @template RequestedType of 'float'|'int'\n     * @param RequestedType $type\n     * @return (RequestedType is 'float' ? float : int)\n     */\n    function convertToNumber(mixed $input, string $type): mixed {\n        throw new Exception('irrelevant - ' . gettype($input) . ' - ' . $type);\n    }\n\n    /**\n     * @template RequestedType of 'float'|'int'\n     * @param RequestedType $type\n     * @return (RequestedType is 'int' ? int : float)\n     */\n    function convertToNumber2(mixed $input, string $type): mixed {\n        throw new Exception('irrelevant - ' . gettype($input) . ' - ' . $type);\n    }\n}"
  },
  {
    "path": "tests/asset/methodWithInterpolatedFloatAndNotFloatParameters.php",
    "content": "<?php\n\nnamespace DisallowFloatsInMethodSignatures;\n\nclass Bar\n{\n    /** @param mixed $d */\n    public function doFoo(\n        float $a,\n        string $b,\n        float $c,\n        $d,\n        float $e\n    ) {\n\n    }\n}\n"
  },
  {
    "path": "tests/asset/property.php",
    "content": "<?php\n\nnamespace DisallowFloatsInProperties;\n\nclass Foo\n{\n\n    /** @var float */\n    private $foo;\n\n    /** @var float|int */\n    private $bar;\n\n    /** @var int */\n    private $baz;\n\n    /** @var mixed */\n    private $taz;\n\n}\n"
  },
  {
    "path": "tests/src/DisallowFloatAssignedToVariableRuleTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStanTest\\Rules\\Floats;\n\nuse PHPStan\\Node\\Printer\\Printer;\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\Testing\\RuleTestCase;\nuse Roave\\PHPStan\\Rules\\Floats\\DisallowFloatAssignedToVariableRule;\n\n/** @extends RuleTestCase<DisallowFloatAssignedToVariableRule> */\nfinal class DisallowFloatAssignedToVariableRuleTest extends RuleTestCase\n{\n    protected function getRule(): Rule\n    {\n        /** @phpstan-ignore phpstanApi.constructor */\n        return new DisallowFloatAssignedToVariableRule(new Printer());\n    }\n\n    public function testRule(): void\n    {\n        $this->analyse([__DIR__ . '/../asset/assign.php'], [\n            [\n                'Cannot assign float to $test - floats are not allowed.',\n                18,\n            ],\n            [\n                'Cannot assign float|int to $test2 - floats are not allowed.',\n                19,\n            ],\n            [\n                'Cannot assign float to $this->foo - floats are not allowed.',\n                21,\n            ],\n            [\n                'Cannot assign float to $this->bar[\\'test\\'] - floats are not allowed.',\n                22,\n            ],\n            [\n                'Cannot assign float to $test - floats are not allowed.',\n                31,\n            ],\n        ]);\n    }\n}\n"
  },
  {
    "path": "tests/src/DisallowFloatEverywhereRuleTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStanTest\\Rules\\Floats;\n\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\Testing\\RuleTestCase;\nuse Roave\\PHPStan\\Rules\\Floats\\DisallowFloatEverywhereRule;\n\n/** @extends RuleTestCase<DisallowFloatEverywhereRule> */\nfinal class DisallowFloatEverywhereRuleTest extends RuleTestCase\n{\n    protected function getRule(): Rule\n    {\n        return new DisallowFloatEverywhereRule();\n    }\n\n    public function testRule(): void\n    {\n        $this->analyse([__DIR__ . '/../asset/expr.php'], [\n            [\n                'Cannot have float as a result type of this expression - floats are not allowed.',\n                6,\n            ],\n            [\n                'Cannot have float as a result type of this expression - floats are not allowed.',\n                7,\n            ],\n            [\n                'Cannot have float as a result type of this expression - floats are not allowed.',\n                7,\n            ],\n            [\n                'Cannot have float as a result type of this expression - floats are not allowed.',\n                10,\n            ],\n        ]);\n    }\n}\n"
  },
  {
    "path": "tests/src/DisallowFloatInFunctionSignatureRuleTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStanTest\\Rules\\Floats;\n\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\Testing\\RuleTestCase;\nuse Roave\\PHPStan\\Rules\\Floats\\DisallowFloatInFunctionSignatureRule;\n\n/** @extends RuleTestCase<DisallowFloatInFunctionSignatureRule> */\nfinal class DisallowFloatInFunctionSignatureRuleTest extends RuleTestCase\n{\n    protected function getRule(): Rule\n    {\n        return new DisallowFloatInFunctionSignatureRule($this->createReflectionProvider());\n    }\n\n    public function testRule(): void\n    {\n        require_once __DIR__ . '/../asset/function.php';\n        $this->analyse([__DIR__ . '/../asset/function.php'], [\n            [\n                'Parameter #1 $float of function DisallowFloatsInFunctionSignatures\\doFoo() cannot have float as its type - floats are not allowed.',\n                11,\n            ],\n            [\n                'Parameter #2 $intOrFloat of function DisallowFloatsInFunctionSignatures\\doFoo() cannot have float|int as its type - floats are not allowed.',\n                11,\n            ],\n            [\n                'Function DisallowFloatsInFunctionSignatures\\doFoo() cannot have float as its return type - floats are not allowed.',\n                11,\n            ],\n        ]);\n    }\n\n    public function testRuleWithoutNamespace(): void\n    {\n        require_once __DIR__ . '/../asset/functionWithoutNamespace.php';\n        $this->analyse([__DIR__ . '/../asset/functionWithoutNamespace.php'], [\n            [\n                'Parameter #1 $float of function doFoo() cannot have float as its type - floats are not allowed.',\n                9,\n            ],\n            [\n                'Parameter #2 $intOrFloat of function doFoo() cannot have float|int as its type - floats are not allowed.',\n                9,\n            ],\n            [\n                'Function doFoo() cannot have float as its return type - floats are not allowed.',\n                9,\n            ],\n        ]);\n    }\n\n    public function testRuleShowsAllFloatParametersAsViolations(): void\n    {\n        require_once __DIR__ . '/../asset/functionWithInterpolatedFloatAndNonFloatParameters.php';\n        $this->analyse([__DIR__ . '/../asset/functionWithInterpolatedFloatAndNonFloatParameters.php'], [\n            [\n                'Parameter #1 $a of function DisallowFloatsInFunctionSignatures\\functionWithInterpolatedFloatAndNonFloatParameters() cannot have float as its type - floats are not allowed.',\n                6,\n            ],\n            [\n                'Parameter #3 $c of function DisallowFloatsInFunctionSignatures\\functionWithInterpolatedFloatAndNonFloatParameters() cannot have float as its type - floats are not allowed.',\n                6,\n            ],\n            [\n                'Parameter #5 $e of function DisallowFloatsInFunctionSignatures\\functionWithInterpolatedFloatAndNonFloatParameters() cannot have float as its type - floats are not allowed.',\n                6,\n            ],\n        ]);\n    }\n\n    public function testNotAutoloadedFunction(): void\n    {\n        $this->analyse(\n            [__DIR__ . '/../asset/functionNotAutoloaded.php'],\n            [\n                [\n                    'Function nonexistentRoaveFunction() cannot have float as its return type - floats are not allowed.',\n                    3,\n                ],\n            ],\n        );\n    }\n}\n"
  },
  {
    "path": "tests/src/DisallowFloatInMethodSignatureRuleTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStanTest\\Rules\\Floats;\n\nuse PhpParser\\Node\\Stmt\\ClassMethod;\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\ShouldNotHappenException;\nuse PHPStan\\Testing\\RuleTestCase;\nuse Roave\\PHPStan\\Rules\\Floats\\DisallowFloatInMethodSignatureRule;\n\n/** @extends RuleTestCase<DisallowFloatInMethodSignatureRule> */\nfinal class DisallowFloatInMethodSignatureRuleTest extends RuleTestCase\n{\n    protected function getRule(): Rule\n    {\n        return new DisallowFloatInMethodSignatureRule();\n    }\n\n    public function testRule(): void\n    {\n        $this->analyse([__DIR__ . '/../asset/method.php'], [\n            [\n                'Parameter #1 $float of method DisallowFloatsInMethodSignatures\\Foo::doFoo() cannot have float as its type - floats are not allowed.',\n                14,\n            ],\n            [\n                'Parameter #2 $intOrFloat of method DisallowFloatsInMethodSignatures\\Foo::doFoo() cannot have float|int as its type - floats are not allowed.',\n                14,\n            ],\n            [\n                'Method DisallowFloatsInMethodSignatures\\Foo::doFoo() cannot have float as its return type - floats are not allowed.',\n                14,\n            ],\n        ]);\n    }\n\n    public function testRuleShowsAllFloatParametersAsViolations(): void\n    {\n        $this->analyse([__DIR__ . '/../asset/methodWithInterpolatedFloatAndNotFloatParameters.php'], [\n            [\n                'Parameter #1 $a of method DisallowFloatsInMethodSignatures\\Bar::doFoo() cannot have float as its type - floats are not allowed.',\n                8,\n            ],\n            [\n                'Parameter #3 $c of method DisallowFloatsInMethodSignatures\\Bar::doFoo() cannot have float as its type - floats are not allowed.',\n                8,\n            ],\n            [\n                'Parameter #5 $e of method DisallowFloatsInMethodSignatures\\Bar::doFoo() cannot have float as its type - floats are not allowed.',\n                8,\n            ],\n        ]);\n    }\n\n    /**\n     * Verifies that conditional return types containing mixed are not flagged as floats.\n     *\n     * @see https://github.com/Roave/no-floaters/issues/126\n     */\n    public function testRuleDoesNotFlagConditionalReturnTypesContainingMixed(): void\n    {\n        $this->analyse(\n            [__DIR__ . '/../asset/methodWithConditionalReturnType.php'],\n            [\n                [\n                    'Method DisallowFloatsInMethodSignatures\\DummyTypeConverter::convertToNumber() cannot have (RequestedType of string is string ? float : int) as its return type - floats are not allowed.',\n                    35,\n                ],\n                [\n                    'Method DisallowFloatsInMethodSignatures\\DummyTypeConverter::convertToNumber2() cannot have (RequestedType of string is string ? int : float) as its return type - floats are not allowed.',\n                    44,\n                ],\n            ],\n        );\n    }\n\n    /**\n     * Verifies that the impossible scenario of a method signature is not declared in a class method\n     */\n    public function testRuleWillNotWorkWhenNotInClassScope(): void\n    {\n        $rule = new DisallowFloatInMethodSignatureRule();\n\n        $node  = self::createStub(ClassMethod::class);\n        $scope = self::createStub(ScopeWithNodeCallbackInvoker::class);\n\n        $scope\n            ->method('isInClass')\n            ->willReturn(false);\n\n        $this->expectException(ShouldNotHappenException::class);\n        $this->expectExceptionMessage('Internal error.');\n\n        $rule->processNode($node, $scope);\n    }\n}\n"
  },
  {
    "path": "tests/src/DisallowFloatPropertyTypeRuleTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStanTest\\Rules\\Floats;\n\nuse PhpParser\\Node\\PropertyItem;\nuse PHPStan\\Rules\\Rule;\nuse PHPStan\\ShouldNotHappenException;\nuse PHPStan\\Testing\\RuleTestCase;\nuse Roave\\PHPStan\\Rules\\Floats\\DisallowFloatPropertyTypeRule;\n\n/** @extends RuleTestCase<DisallowFloatPropertyTypeRule> */\nfinal class DisallowFloatPropertyTypeRuleTest extends RuleTestCase\n{\n    protected function getRule(): Rule\n    {\n        return new DisallowFloatPropertyTypeRule();\n    }\n\n    public function testRule(): void\n    {\n        $this->analyse([__DIR__ . '/../asset/property.php'], [\n            [\n                'Property DisallowFloatsInProperties\\Foo::$foo cannot have float as its type - floats are not allowed.',\n                9,\n            ],\n            [\n                'Property DisallowFloatsInProperties\\Foo::$bar cannot have float|int as its type - floats are not allowed.',\n                12,\n            ],\n        ]);\n    }\n\n    /**\n     * Verifies that the impossible scenario of a method signature is not declared in a class method\n     */\n    public function testRuleWillNotWorkWhenNotInClassScope(): void\n    {\n        $rule = new DisallowFloatPropertyTypeRule();\n\n        $node  = self::createStub(PropertyItem::class);\n        $scope = self::createStub(ScopeWithNodeCallbackInvoker::class);\n\n        $scope\n            ->method('isInClass')\n            ->willReturn(false);\n\n        $this->expectException(ShouldNotHappenException::class);\n        $this->expectExceptionMessage('Internal error.');\n\n        $rule->processNode($node, $scope);\n    }\n}\n"
  },
  {
    "path": "tests/src/ScopeWithNodeCallbackInvoker.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Roave\\PHPStanTest\\Rules\\Floats;\n\nuse PHPStan\\Analyser\\NodeCallbackInvoker;\nuse PHPStan\\Analyser\\Scope;\n\n/** @phpstan-ignore phpstanApi.interface */\ninterface ScopeWithNodeCallbackInvoker extends Scope, NodeCallbackInvoker\n{\n}\n"
  }
]