Compare commits

...
Author SHA1 Message Date
Barry vd. Heuvel 8495c55fe0 update strings 2025-07-17 08:16:09 +02:00
Barry vd. Heuvel 12c891a0bf UPdate snapshots 2025-07-17 08:11:33 +02:00
Barry vd. Heuvel f4e23dae5e Update version restraint 2025-07-17 08:11:29 +02:00
Pieter Willekens fafe264b3c fix(ModelsCommand): use 'string' as realType for 'encrypted' casts (#1698) 2025-07-17 08:06:36 +02:00
erikn69 108f6269c1 Update .gitattributes - avoid all .php-cs-fixer files on vendor (#1708) 2025-07-17 08:02:50 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> c488262f97 Bump stefanzweifel/git-auto-commit-action from 5 to 6 in the deps group (#1719)
Bumps the deps group with 1 update: [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action).


Updates `stefanzweifel/git-auto-commit-action` from 5 to 6
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: deps
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-17 08:02:35 +02:00
Barry vd. Heuvel 83e3f39b39 Fix tests on windows (#1720)
* Update run-tests.yml

* Update snapshot

* Simplify matrix
2025-07-17 08:02:25 +02:00
laravel-ide-helper 31979ed485 composer fix-style 2025-07-17 05:52:57 +00:00
erikn69 6d96f0bd1a Support other OS on tests (#1715) 2025-07-17 07:52:32 +02:00
Kristijan cff244b9b5 fix: Fixed wrong doc for softDeletes withTrashed method (#1688) 2025-07-17 07:50:16 +02:00
laravel-ide-helper 4dfc08a854 composer fix-style 2025-07-17 05:24:13 +00:00
erikn69 6c4ba2ad38 Support AsCollection::of($map), AsCollection::using($class, $map) (#1714)
* Support `AsCollection::of($map)`, `AsCollection::using($class, $map)`

* test compatibility(`of($map)`,`using($class, $map)` compiled), only laravel `>=12.10`
2025-07-17 07:23:52 +02:00
Robin Rosiers 1815a6140a Add multi-level directory support for translation files (#1718) 2025-06-30 13:27:12 +02:00
Santos VilanculosandMarkus Podar 7c469e4073 docs(readme): add Laravel 12 support information (#1717)
* docs(readme): add Laravel 12 support information

* docs(readme): update Laravel support information

Co-authored-by: Markus Podar <[email protected]>

---------

Co-authored-by: Markus Podar <[email protected]>
2025-06-30 13:09:32 +02:00
laravel-ide-helper ae0a06d406 composer fix-style 2025-05-15 07:57:32 +00:00
erikn69 e0b2f86326 Configurable macro return type defaults (#1711) 2025-05-15 09:56:31 +02:00
laravel-ide-helper cdefaeed42 composer fix-style 2025-05-14 18:21:46 +00:00
erikn69 c775aec1bb Revert #1629 - _Allow adding custom Macroable classes_ (#1707)
* Revert #1629 - Allow adding custom Macroable classes

* Add Macros test
2025-05-14 20:21:17 +02:00
Marvin Naumann 0fa96e572d detect default parameter from type float and adding tests for scopes with typed parameters (#1697) 2025-04-22 15:31:43 +02:00
8eec4f1ff5 feat(ModelsCommand): add support for the new Scope attribute (#1694)
* composer fix-style

* feat(model): add support for new Scope attribute

* composer fix-style

* snapshot

* check if class_exists for psalm

* check if class_exists for psalm

* resolve psalm issue

* remove prefix slash

* revert whitespace changes

* composer fix-style

* Update composer.json

---------

Co-authored-by: laravel-ide-helper <[email protected]>
Co-authored-by: Barry vd. Heuvel <[email protected]>
2025-04-04 16:14:00 +02:00
Pieter Willekens d567978ebe chore(meta): ignore abstracts in the autoloader (Fixes #1671) (#1686) 2025-02-27 20:19:11 +01:00
KentarouTakeda 09623f216c Add extends declaration for Macroable classes to fix missing inherited methods (#1674) 2025-02-22 16:59:08 +01:00
Tom Westrick 3d4e37798e Fix AsArrayObject cast to be Laravel's ArrayObject (#1675) 2025-02-22 15:16:07 +01:00
barryvdh 713a4758f9 Update CHANGELOG 2025-02-21 15:09:51 +00:00
barryvdh 8d441ec99f normalize composer.json 2025-02-11 13:59:46 +00:00
dba153f1e0 Laravel 12 support (#1672)
* Laravel 12 support

* Update run-integration-tests.yml to include Laravel 12

* Update run-tests.yml to include Laravel 12

* allow testbench ^10

* Update run-integration-tests.yml

* Update run-tests.yml

* Update composer.json

Co-authored-by: KentarouTakeda <[email protected]>

* Update run-integration-tests.yml

* Update run-tests.yml

---------

Co-authored-by: KentarouTakeda <[email protected]>
Co-authored-by: Barry vd. Heuvel <[email protected]>
2025-02-11 14:59:28 +01:00
yparitcher 40485e7350 Fix MorphTo Model Doc Generation (#1668)
fix:
```php
    /**
     * @return MorphTo<contravariant ModelA|ModelB, $this>
     */
    public function reminderable(): MorphTo {
        return $this->morphTo(__FUNCTION__, 'entity', 'entity_id');
    }
```
From:
```php
* @property-read contravariant ModelA|ModelB $reminderable
 ```
To:
```php
* @property-read ModelA|ModelB $reminderable
 ```
Fixes: #1667
2025-02-04 17:49:42 +01:00
skyler544andSkyler Mayfield ead24b10f6 prevent generation of incorrect property annotation (#1665)
Co-authored-by: Skyler Mayfield <[email protected]>
2025-01-29 22:43:43 +01:00
Kristijan 187ce9beeb Update configs.php (#1662)
Fixes config items incorectlly set as `string` due to `'array(...)'` value passed to `gettype` instead of real array
2025-01-23 18:56:10 +01:00
barryvdh 6b43ac616d Update CHANGELOG 2025-01-14 09:07:42 +00:00
Barry vd. Heuvel 980a87e250 Check if returnType from docblock is not null (#1658) 2025-01-14 10:07:00 +01:00
Barry vd. Heuvelandlaravel-ide-helper 299a81b9bb Convert auth() helper to use Auth facade (#1656)
* Convert auth() helper to use Auth facade

* composer fix-style

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2025-01-08 13:50:47 +01:00
barryvdh 06c1fab9b5 Update CHANGELOG 2025-01-08 10:03:44 +00:00
Casper Bloemendaal 271682a2a6 feat: use generics of return type to determine resulting models (#1653) 2025-01-08 11:01:30 +01:00
Barry vd. Heuvelandlaravel-ide-helper bb1caed698 Check if macro is valid (#1655)
* Check if macro is valid

* composer fix-style

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2025-01-08 11:00:53 +01:00
Barry vd. Heuvelandlaravel-ide-helper 55268cd47a Catch meta, tweak auth (#1654)
* Catch meta, tweak auth

* composer fix-style

* Catch meta, tweak auth

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2025-01-08 11:00:41 +01:00
barryvdh 088968c3fc Update CHANGELOG 2025-01-06 15:42:30 +00:00
Barry vd. Heuvel 655e057626 Fix empty closure 2025-01-06 16:29:58 +01:00
barryvdh c8d85a0d34 Update CHANGELOG 2025-01-06 14:09:45 +00:00
Barry vd. Heuvel 4c656cc71d Remove duplicate config, fix ->can() (#1650) 2025-01-06 15:08:47 +01:00
barryvdh 0fe9774dfb Update CHANGELOG 2025-01-06 13:53:52 +00:00
Jesper Noordsij 030f6f1f35 Add special 'dev' to composer keywords (#1649) 2025-01-03 15:21:18 +01:00
laravel-ide-helper 154300fb06 composer fix-style 2025-01-01 12:17:43 +00:00
Mathieu TUDISCOandBarry vd. Heuvel 05d9c3cd65 Allow adding custom Macroable classes. (#1629)
* Allow adding custom Macroable classes.

* Remove duplication, tweak config

* Remove test

---------

Co-authored-by: Barry vd. Heuvel <[email protected]>
2025-01-01 13:17:20 +01:00
Barry vd. Heuvelandlaravel-ide-helper beda399e7e Feat guess macro types (#1648)
* Add default class for HttpClient macro

* composer fix-style

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2025-01-01 10:44:43 +01:00
Nereo Berardozzi 0bbca8f5e2 Fixed generating PHPDoc for methods with class templates (#1647)
* Fixed generating PHPDoc for methods with class templates

* Fix style

* Use getter for alias template names

* Fixed missing class in static analysis
2024-12-31 17:18:28 +01:00
Barry vd. Heuvelandlaravel-ide-helper f8381565ad Add more metadata (#1646)
* Add more metadata

* composer fix-style

* Parse .env

* composer fix-style

* Check if .env exists

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2024-12-30 15:06:36 +01:00
Barry vd. Heuvel cffcd07e98 Also add eloquent template tags from base class (#1645) 2024-12-30 12:58:28 +01:00
Barry vd. Heuvelandlaravel-ide-helper 9c6380da4a Remove php parser (#1644)
* Remove php parser

* composer fix-style

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2024-12-30 12:42:35 +01:00
Barry vd. Heuvelandlaravel-ide-helper e509790805 Use forked ContextFactory (#1643)
* Use forked ContextFactory

* composer fix-style

* Trim slashes

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2024-12-30 12:03:45 +01:00
Barry vd. Heuvelandlaravel-ide-helper 791ba555f4 Add meta override for user return types (#1642)
* Add meta override for user return types

* composer fix-style

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2024-12-30 10:31:30 +01:00
Barry vd. Heuvel c324438731 Bump to 3.5 2024-12-29 19:44:30 +01:00
Barry vd. Heuvelandlaravel-ide-helper 4e4da0825a Add phpstorm meta argument hints (#1640)
* Add phpstorm meta hints

* composer fix-style

* Use php-templates from vs-code

* Fix view instance

* composer fix-style

* Add translations

* composer fix-style

* map to string

* composer fix-style

* Fix test

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2024-12-29 19:44:08 +01:00
barryvdh 66ea6aa57b Update CHANGELOG 2024-12-29 13:26:59 +00:00
87 changed files with 1875 additions and 501 deletions
+1 -3
View File
@@ -6,9 +6,7 @@
/.gitattributes export-ignore /.gitattributes export-ignore
/.github export-ignore /.github export-ignore
/.gitignore export-ignore /.gitignore export-ignore
/.php-cs-fixer.cache export-ignore /.php-cs-fixer* export-ignore
/.php-cs-fixer.php export-ignore
/.php-cs-fixer.tests.cache export-ignore
/phpunit.xml.dist export-ignore /phpunit.xml.dist export-ignore
/psalm-baseline.xml export-ignore /psalm-baseline.xml export-ignore
/psalm.xml export-ignore /psalm.xml export-ignore
+1 -1
View File
@@ -23,6 +23,6 @@ jobs:
composer global require ergebnis/composer-normalize composer global require ergebnis/composer-normalize
composer normalize composer normalize
- uses: stefanzweifel/git-auto-commit-action@v5 - uses: stefanzweifel/git-auto-commit-action@v6
with: with:
commit_message: normalize composer.json commit_message: normalize composer.json
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
- run: composer fix-style - run: composer fix-style
continue-on-error: true continue-on-error: true
- uses: stefanzweifel/git-auto-commit-action@v5 - uses: stefanzweifel/git-auto-commit-action@v6
with: with:
commit_message: composer fix-style commit_message: composer fix-style
commit_author: laravel-ide-helper <[email protected]> commit_author: laravel-ide-helper <[email protected]>
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
php: [8.4, 8.3, 8.2] php: [8.4, 8.3, 8.2]
laravel: [^11.15] laravel: [11.x, 12.x]
name: P${{ matrix.php }} - Laravel${{ matrix.laravel }} name: P${{ matrix.php }} - Laravel${{ matrix.laravel }}
steps: steps:
+8 -3
View File
@@ -20,13 +20,18 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-22.04, windows-2019] os: [ubuntu-latest]
php: [8.4, 8.3, 8.2] php: [8.4, 8.3, 8.2]
laravel: [^11.15] laravel: [~11.15, 12.x]
stability: [prefer-lowest, prefer-stable] stability: [prefer-lowest, prefer-stable]
include:
- os: windows-latest
php: 8.3
laravel: 12.x
stability: prefer-stable
steps: steps:
- name: Set git to use LF - name: Set git to use LF
if: ${{ matrix.os == 'windows-2019' }} if: ${{ matrix.os == 'windows-latest' }}
run: | run: |
git config --global core.autocrlf false git config --global core.autocrlf false
git config --global core.eol lf git config --global core.eol lf
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
release-notes: ${{ github.event.release.body }} release-notes: ${{ github.event.release.body }}
- name: Commit updated CHANGELOG - name: Commit updated CHANGELOG
uses: stefanzweifel/git-auto-commit-action@v5 uses: stefanzweifel/git-auto-commit-action@v6
with: with:
branch: ${{ github.event.release.target_commitish }} branch: ${{ github.event.release.target_commitish }}
commit_message: Update CHANGELOG commit_message: Update CHANGELOG
+109 -1
View File
@@ -1,5 +1,110 @@
# Changelog # Changelog
## v3.5.5 - 2025-02-21
### What's Changed
* Fix for incorrect config item types in meta file by @eldair in https://github.com/barryvdh/laravel-ide-helper/pull/1662
* Prevent generation of incorrect property annotation by @skyler544 in https://github.com/barryvdh/laravel-ide-helper/pull/1665
* Fix MorphTo Model Doc Generation by @yparitcher in https://github.com/barryvdh/laravel-ide-helper/pull/1668
* Laravel 12 support by @jonnott in https://github.com/barryvdh/laravel-ide-helper/pull/1672
### New Contributors
* @eldair made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1662
* @skyler544 made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1665
* @yparitcher made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1668
* @jonnott made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1672
**Full Changelog**: https://github.com/barryvdh/laravel-ide-helper/compare/v3.5.4...v3.5.5
## v3.5.4 - 2025-01-14
### What's Changed
* Convert auth() helper to use Auth facade by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1656
* Check if returnType from docblock is not null by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1658
**Full Changelog**: https://github.com/barryvdh/laravel-ide-helper/compare/v3.5.3...v3.5.4
## v3.5.3 - 2025-01-08
### What's Changed
* Catch meta, tweak auth by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1654
* Check if macro is valid by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1655
* feat: use generics of return type to determine resulting models by @Bloemendaal in https://github.com/barryvdh/laravel-ide-helper/pull/1653
### New Contributors
* @Bloemendaal made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1653
**Full Changelog**: https://github.com/barryvdh/laravel-ide-helper/compare/v3.5.2...v3.5.3
## v3.5.2 - 2025-01-06
### Fixes
Fix empty/anonymous closure in meta command.
**Full Changelog**: https://github.com/barryvdh/laravel-ide-helper/compare/v3.5.1...v3.5.2
## v3.5.1 - 2025-01-06
### What's Changed
* Remove duplicate config, fix ->can() by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1650
**Full Changelog**: https://github.com/barryvdh/laravel-ide-helper/compare/v3.5.0...v3.5.1
## v3.5.0 - 2025-01-06
### What's Changed
* Add phpstorm meta argument hints by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1640
* Add meta override for user return types by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1642
* Use forked ContextFactory by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1643
* Remove php parser by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1644
* Also add eloquent template tags from base class by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1645
* Add more metadata by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1646
* Fixed generating PHPDoc for methods with class templates by @chack1172 in https://github.com/barryvdh/laravel-ide-helper/pull/1647
* Feat guess macro types by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1648
* Allow adding custom Macroable classes. by @mathieutu in https://github.com/barryvdh/laravel-ide-helper/pull/1629
* Add special `dev` to composer keywords by @jnoordsij in https://github.com/barryvdh/laravel-ide-helper/pull/1649
### New Contributors
* @chack1172 made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1647
* @mathieutu made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1629
* @jnoordsij made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1649
**Full Changelog**: https://github.com/barryvdh/laravel-ide-helper/compare/v3.4.0...v3.5.0
## v3.4.0 - 2024-12-29
### What's Changed
* fix: add @template TModel of static for Eloquent by @imzyf in https://github.com/barryvdh/laravel-ide-helper/pull/1631
* Add templates to Eloquent by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1634
* Update testsuite for Generator, simplify service provider and mock by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1635
* Add option for only eloquent by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1636
* Add weak generics for array type objects by @LauJosefsen in https://github.com/barryvdh/laravel-ide-helper/pull/1621
* Make all "note" in README apply quote style by @hms5232 in https://github.com/barryvdh/laravel-ide-helper/pull/1590
* Update README.md by @Mtillmann in https://github.com/barryvdh/laravel-ide-helper/pull/1587
* Rename view var by @barryvdh and @pb30 in https://github.com/barryvdh/laravel-ide-helper/pull/1637 and https://github.com/barryvdh/laravel-ide-helper/pull/1563
* Format IDE helper by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1638
* Add TLDR section, update options by @barryvdh in https://github.com/barryvdh/laravel-ide-helper/pull/1639
### New Contributors
* @imzyf made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1631
* @LauJosefsen made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1621
* @hms5232 made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1590
* @Mtillmann made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1587
* @pb30 made their first contribution in https://github.com/barryvdh/laravel-ide-helper/pull/1563
**Full Changelog**: https://github.com/barryvdh/laravel-ide-helper/compare/v3.3.0...v3.4.0
## v3.3.0 - 2024-12-18 ## v3.3.0 - 2024-12-18
### What's Changed ### What's Changed
@@ -54,10 +159,13 @@
- Fix type of hashed model property to `string` - Fix type of hashed model property to `string`
### Changed ### Changed
- Update view "version" variable name to avoid potential conflicts
- Update view "version" variable name to avoid potential conflicts
- Add support for EloquentBuilder generics introduced in Laravel 11.15. - Add support for EloquentBuilder generics introduced in Laravel 11.15.
- Drop support for Laravel versions earlier than 11.15. - Drop support for Laravel versions earlier than 11.15.
### Added ### Added
+1 -1
View File
@@ -11,7 +11,7 @@
This package generates helper files that enable your IDE to provide accurate autocompletion. This package generates helper files that enable your IDE to provide accurate autocompletion.
Generation is done based on the files in your project, so they are always up-to-date. Generation is done based on the files in your project, so they are always up-to-date.
The 3.x branch supports Laravel 10 and 11. For older version, use the 2.x releases. The 3.x branch supports Laravel 10 and later. For older version, use the 2.x releases.
- [Installation](#installation) - [Installation](#installation)
- [Usage](#usage) - [Usage](#usage)
+14 -14
View File
@@ -11,7 +11,8 @@
"netbeans", "netbeans",
"sublime", "sublime",
"codeintel", "codeintel",
"phpdoc" "phpdoc",
"dev"
], ],
"authors": [ "authors": [
{ {
@@ -22,25 +23,24 @@
"require": { "require": {
"php": "^8.2", "php": "^8.2",
"ext-json": "*", "ext-json": "*",
"barryvdh/reflection-docblock": "^2.2", "barryvdh/reflection-docblock": "^2.4",
"composer/class-map-generator": "^1.0", "composer/class-map-generator": "^1.0",
"illuminate/console": "^11.15", "illuminate/console": "^11.15 || ^12",
"illuminate/database": "^11.15", "illuminate/database": "^11.15 || ^12",
"illuminate/filesystem": "^11.15", "illuminate/filesystem": "^11.15 || ^12",
"illuminate/support": "^11.15", "illuminate/support": "^11.15 || ^12"
"nikic/php-parser": "^4.18 || ^5",
"phpdocumentor/type-resolver": "^1.1.0"
}, },
"require-dev": { "require-dev": {
"ext-pdo_sqlite": "*", "ext-pdo_sqlite": "*",
"friendsofphp/php-cs-fixer": "^3", "friendsofphp/php-cs-fixer": "^3",
"illuminate/config": "^11.15", "illuminate/config": "^11.15 || ^12",
"illuminate/view": "^11.15", "illuminate/view": "^11.15 || ^12",
"mockery/mockery": "^1.4", "mockery/mockery": "^1.4",
"orchestra/testbench": "^9.2", "orchestra/testbench": "^9.2 || ^10",
"phpunit/phpunit": "^10.5", "phpunit/phpunit": "^10.5 || ^11.5.3",
"spatie/phpunit-snapshot-assertions": "^4 || ^5", "spatie/phpunit-snapshot-assertions": "^4 || ^5",
"vimeo/psalm": "^5.4" "vimeo/psalm": "^5.4",
"vlucas/phpdotenv": "^5"
}, },
"suggest": { "suggest": {
"illuminate/events": "Required for automatic helper generation (^6|^7|^8|^9|^10|^11)." "illuminate/events": "Required for automatic helper generation (^6|^7|^8|^9|^10|^11)."
@@ -65,7 +65,7 @@
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "3.4-dev" "dev-master": "3.5-dev"
}, },
"laravel": { "laravel": {
"providers": [ "providers": [
+15
View File
@@ -123,6 +123,7 @@ return [
'helper_files' => [ 'helper_files' => [
base_path() . '/vendor/laravel/framework/src/Illuminate/Support/helpers.php', base_path() . '/vendor/laravel/framework/src/Illuminate/Support/helpers.php',
base_path() . '/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php',
], ],
/* /*
@@ -273,6 +274,20 @@ return [
*/ */
'use_generics_annotations' => true, 'use_generics_annotations' => true,
/*
|--------------------------------------------------------------------------
| Default return types for macros
|--------------------------------------------------------------------------
|
| Define default return types for macros without explicit return types.
| e.g. `\Illuminate\Database\Query\Builder::class => 'static'`,
| `\Illuminate\Support\Str::class => 'string'`
|
*/
'macro_default_return_types' => [
Illuminate\Http\Client\Factory::class => Illuminate\Http\Client\PendingRequest::class,
],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Additional relation types | Additional relation types
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Taylor Otwell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+5
View File
@@ -0,0 +1,5 @@
The templates here are based on the official VS Code extension by Laravel https://github.com/laravel/vs-code-extension
Modifications:
- return instead of echo
- do not serialize to JSON
+43
View File
@@ -0,0 +1,43 @@
<?php
return collect(Illuminate\Support\Facades\Gate::abilities())
->map(function ($policy, $key) {
$reflection = new ReflectionFunction($policy);
$policyClass = null;
$closureThis = $reflection->getClosureThis();
if ($closureThis && get_class($closureThis) === Illuminate\Auth\Access\Gate::class) {
$vars = $reflection->getClosureUsedVariables();
if (isset($vars['callback'])) {
[$policyClass, $method] = explode('@', $vars['callback']);
$reflection = new ReflectionMethod($policyClass, $method);
}
}
return [
'key' => $key,
'uri' => $reflection->getFileName(),
'policy_class' => $policyClass,
'lineNumber' => $reflection->getStartLine(),
];
})
->merge(
collect(Illuminate\Support\Facades\Gate::policies())->flatMap(function ($policy, $model) {
$methods = (new ReflectionClass($policy))->getMethods();
return collect($methods)->map(function (ReflectionMethod $method) use ($policy) {
return [
'key' => $method->getName(),
'uri' => $method->getFileName(),
'policy_class' => $policy,
'lineNumber' => $method->getStartLine(),
];
})->filter(function ($ability) {
return !in_array($ability['key'], ['allow', 'deny']);
});
}),
)
->values()
->groupBy('key');
+131
View File
@@ -0,0 +1,131 @@
<?php
$local = collect(glob(config_path('/*.php')))
->merge(glob(config_path('**/*.php')))
->map(fn ($path) => [
(string) Illuminate\Support\Str::of($path)
->replace([config_path('/'), '.php'], '')
->replace('/', '.'),
$path,
]);
$vendor = collect(glob(base_path('vendor/**/**/config/*.php')))->map(fn (
$path
) => [
(string) Illuminate\Support\Str::of($path)
->afterLast('/config/')
->replace('.php', '')
->replace('/', '.'),
$path,
]);
$configPaths = $local
->merge($vendor)
->groupBy(0)
->map(fn ($items) => $items->pluck(1));
$cachedContents = [];
$cachedParsed = [];
function vsCodeGetConfigValue($value, $key, $configPaths)
{
$parts = explode('.', $key);
$toFind = $key;
$found = null;
while (count($parts) > 0) {
array_pop($parts);
$toFind = implode('.', $parts);
if ($configPaths->has($toFind)) {
$found = $toFind;
break;
}
}
if ($found === null) {
return null;
}
$file = null;
$line = null;
if ($found === $key) {
$file = $configPaths->get($found)[0];
} else {
foreach ($configPaths->get($found) as $path) {
$cachedContents[$path] ??= file_get_contents($path);
$cachedParsed[$path] ??= token_get_all($cachedContents[$path]);
$keysToFind = Illuminate\Support\Str::of($key)
->replaceFirst($found, '')
->ltrim('.')
->explode('.');
if (is_numeric($keysToFind->last())) {
$index = $keysToFind->pop();
if ($index !== '0') {
return null;
}
$key = collect(explode('.', $key));
$key->pop();
$key = $key->implode('.');
$value = [];
}
$nextKey = $keysToFind->shift();
$expectedDepth = 1;
$depth = 0;
foreach ($cachedParsed[$path] as $token) {
if ($token === '[') {
$depth++;
}
if ($token === ']') {
$depth--;
}
if (!is_array($token)) {
continue;
}
$str = trim($token[1], '"\'');
if (
$str === $nextKey &&
$depth === $expectedDepth &&
$token[0] === T_CONSTANT_ENCAPSED_STRING
) {
$nextKey = $keysToFind->shift();
$expectedDepth++;
if ($nextKey === null) {
$file = $path;
$line = $token[2];
break;
}
}
}
if ($file) {
break;
}
}
}
return [
'name' => $key,
'value' => $value,
'file' => $file === null ? null : str_replace(base_path('/'), '', $file),
'line' => $line,
];
}
return collect(Illuminate\Support\Arr::dot(config()->all()))
->map(fn ($value, $key) => vsCodeGetConfigValue($value, $key, $configPaths))
->filter()
->values();
+64
View File
@@ -0,0 +1,64 @@
<?php
return collect(app("Illuminate\Contracts\Http\Kernel")->getMiddlewareGroups())
->merge(app("Illuminate\Contracts\Http\Kernel")->getRouteMiddleware())
->map(function ($middleware, $key) {
$result = [
'class' => null,
'uri' => null,
'startLine' => null,
'parameters' => null,
'groups' => [],
];
if (is_array($middleware)) {
$result['groups'] = collect($middleware)->map(function ($m) {
if (!class_exists($m)) {
return [
'class' => $m,
'uri' => null,
'startLine' => null,
];
}
$reflected = new ReflectionClass($m);
$reflectedMethod = $reflected->getMethod('handle');
return [
'class' => $m,
'uri' => $reflected->getFileName(),
'startLine' =>
$reflectedMethod->getFileName() === $reflected->getFileName()
? $reflectedMethod->getStartLine()
: null,
];
})->all();
return $result;
}
$reflected = new ReflectionClass($middleware);
$reflectedMethod = $reflected->getMethod('handle');
$result = array_merge($result, [
'class' => $middleware,
'uri' => $reflected->getFileName(),
'startLine' => $reflectedMethod->getStartLine(),
]);
$parameters = collect($reflectedMethod->getParameters())
->filter(function ($rc) {
return $rc->getName() !== 'request' && $rc->getName() !== 'next';
})
->map(function ($rc) {
return $rc->getName() . ($rc->isVariadic() ? '...' : '');
});
if ($parameters->isEmpty()) {
return $result;
}
return array_merge($result, [
'parameters' => $parameters->implode(','),
]);
});
+46
View File
@@ -0,0 +1,46 @@
<?php
function vsCodeGetRouterReflection(Illuminate\Routing\Route $route)
{
if ($route->getActionName() === 'Closure') {
return new ReflectionFunction($route->getAction()['uses']);
}
if (!str_contains($route->getActionName(), '@')) {
return new ReflectionClass($route->getActionName());
}
try {
return new ReflectionMethod($route->getControllerClass(), $route->getActionMethod());
} catch (Throwable $e) {
$namespace = app(Illuminate\Routing\UrlGenerator::class)->getRootControllerNamespace()
?? (app()->getNamespace() . 'Http\Controllers');
return new ReflectionMethod(
$namespace . '\\' . ltrim($route->getControllerClass(), '\\'),
$route->getActionMethod(),
);
}
}
return collect(app('router')->getRoutes()->getRoutes())
->map(function (Illuminate\Routing\Route $route) {
try {
$reflection = vsCodeGetRouterReflection($route);
} catch (Throwable $e) {
$reflection = null;
}
return [
'method' => collect($route->methods())->filter(function ($method) {
return $method !== 'HEAD';
})->implode('|'),
'uri' => $route->uri(),
'name' => $route->getName(),
'action' => $route->getActionName(),
'parameters' => $route->parameterNames(),
'filename' => $reflection ? $reflection->getFileName() : null,
'line' => $reflection ? $reflection->getStartLine() : null,
];
})
;
+161
View File
@@ -0,0 +1,161 @@
<?php
function vsCodeGetTranslationsFromFile(Symfony\Component\Finder\SplFileInfo $file, $path, $namespace)
{
if ($file->getExtension() !== 'php') {
return null;
}
$filePath = $file->getRealPath();
$relativePath = trim(str_replace($path, '', $file->getPath()), DIRECTORY_SEPARATOR);
$lang = explode(DIRECTORY_SEPARATOR, $relativePath)[0] ?? null;
if (!$lang) {
return null;
}
$keyPath = str_replace($path . DIRECTORY_SEPARATOR . $lang . DIRECTORY_SEPARATOR, '', $filePath);
$keyWithSlashes = str_replace('.php', '', $keyPath);
$baseKey = str_replace(DIRECTORY_SEPARATOR, '.', $keyWithSlashes);
if ($namespace) {
$baseKey = "{$namespace}::{$baseKey}";
}
try {
$translations = require $filePath;
} catch (Throwable $e) {
return null;
}
if (!is_array($translations)) {
return null;
}
$fileLines = Illuminate\Support\Facades\File::lines($filePath);
$lines = [];
$inComment = false;
foreach ($fileLines as $index => $line) {
$trimmed = trim($line);
if (str_starts_with($trimmed, '/*')) {
$inComment = true;
}
if ($inComment) {
if (str_ends_with($trimmed, '*/')) {
$inComment = false;
}
continue;
}
if (str_starts_with($trimmed, '//')) {
continue;
}
$lines[] = [$index + 1, $trimmed];
}
return [
'k' => $baseKey,
'la' => $lang,
'vs' => collect(Illuminate\Support\Arr::dot($translations))
->map(
fn ($value, $dotKey) => vsCodeTranslationValue(
$dotKey,
$value,
str_replace(base_path(DIRECTORY_SEPARATOR), '', $filePath),
$lines
)
)
->filter(),
];
}
function vsCodeTranslationValue($key, $value, $file, $lines): ?array
{
if (is_array($value)) {
return null;
}
$lineNumber = 1;
$keys = explode('.', $key);
$currentKey = array_shift($keys);
foreach ($lines as $line) {
if (
strpos($line[1], '"' . $currentKey . '"') !== false ||
strpos($line[1], "'" . $currentKey . "'") !== false
) {
$lineNumber = $line[0];
$currentKey = array_shift($keys);
}
if ($currentKey === null) {
break;
}
}
return [
'v' => $value,
'p' => $file,
'li' => $lineNumber,
'pa' => preg_match_all("/\:([A-Za-z0-9_]+)/", $value, $matches)
? $matches[1]
: [],
];
}
function vscodeCollectTranslations(string $path, ?string $namespace = null)
{
$realPath = realpath($path);
if (!is_dir($realPath)) {
return collect();
}
return collect(Illuminate\Support\Facades\File::allFiles($realPath))
->map(fn ($file) => vsCodeGetTranslationsFromFile($file, $path, $namespace))
->filter();
}
$loader = app('translator')->getLoader();
$namespaces = $loader->namespaces();
$reflection = new ReflectionClass($loader);
$property = $reflection->hasProperty('paths')
? $reflection->getProperty('paths')
: $reflection->getProperty('path');
$property->setAccessible(true);
$paths = Illuminate\Support\Arr::wrap($property->getValue($loader));
$default = collect($paths)->flatMap(
fn ($path) => vscodeCollectTranslations($path)
);
$namespaced = collect($namespaces)->flatMap(
fn ($path, $namespace) => vscodeCollectTranslations($path, $namespace)
);
$final = [];
foreach ($default->merge($namespaced) as $value) {
if (!isset($value['vs']) || !is_iterable($value['vs'])) {
continue;
}
foreach ($value['vs'] as $key => $v) {
$dotKey = "{$value['k']}.{$key}";
if (!isset($final[$dotKey])) {
$final[$dotKey] = [];
}
$final[$dotKey][$value['la']] = $v;
if ($value['la'] === Illuminate\Support\Facades\App::currentLocale()) {
$final[$dotKey]['default'] = $v;
}
}
}
return collect($final);
+61
View File
@@ -0,0 +1,61 @@
<?php
function vsCodeFindBladeFiles($path)
{
$paths = [];
if (!is_dir($path)) {
return $paths;
}
foreach (
Symfony\Component\Finder\Finder::create()
->files()
->name('*.blade.php')
->in($path) as $file
) {
$paths[] = [
'path' => str_replace(base_path(DIRECTORY_SEPARATOR), '', $file->getRealPath()),
'isVendor' => str_contains($file->getRealPath(), base_path('vendor')),
'key' => Illuminate\Support\Str::of($file->getRealPath())
->replace(realpath($path), '')
->replace('.blade.php', '')
->ltrim(DIRECTORY_SEPARATOR)
->replace(DIRECTORY_SEPARATOR, '.'),
];
}
return $paths;
}
$paths = collect(
app('view')
->getFinder()
->getPaths()
)->flatMap(function ($path) {
return vsCodeFindBladeFiles($path);
});
$hints = collect(
app('view')
->getFinder()
->getHints()
)->flatMap(function ($paths, $key) {
return collect($paths)->flatMap(function ($path) use ($key) {
return collect(vsCodeFindBladeFiles($path))->map(function ($value) use (
$key
) {
return array_merge($value, ['key' => "{$key}::{$value['key']}"]);
});
});
});
[$local, $vendor] = $paths
->merge($hints)
->values()
->partition(function ($v) {
return !$v['isVendor'];
});
return $local
->sortBy('key', SORT_NATURAL)
->merge($vendor->sortBy('key', SORT_NATURAL));
+2 -2
View File
@@ -29,7 +29,7 @@ $s3 = $s1 . $s2;
<?php foreach ($namespaces_by_extends_ns as $namespace => $aliases) : ?> <?php foreach ($namespaces_by_extends_ns as $namespace => $aliases) : ?>
namespace <?= $namespace === '__root' ? '' : trim($namespace, '\\') ?> { namespace <?= $namespace === '__root' ? '' : trim($namespace, '\\') ?> {
<?php foreach ($aliases as $alias) : ?> <?php foreach ($aliases as $alias) : ?>
<?php echo trim($alias->getDocComment($s1)) . "\n{$s1}" . $alias->getClassType() ?> <?= $alias->getExtendsClass() ?> { <?php echo trim($alias->getDocComment($s1)) . "\n{$s1}" . $alias->getClassType() ?> <?= $alias->getExtendsClass() ?><?php if ($alias->shouldExtendParentClass()): ?> extends <?= $alias->getParentClass() ?><?php endif; ?> {
<?php foreach ($alias->getMethods() as $method) : ?> <?php foreach ($alias->getMethods() as $method) : ?>
<?= trim($method->getDocComment($s2)) . "\n{$s2}" ?>public static function <?= $method->getName() ?>(<?= $method->getParamsWithDefault() ?>) <?= trim($method->getDocComment($s2)) . "\n{$s2}" ?>public static function <?= $method->getName() ?>(<?= $method->getParamsWithDefault() ?>)
{<?php if ($method->getDeclaringClass() !== $method->getRoot()) : ?> {<?php if ($method->getDeclaringClass() !== $method->getRoot()) : ?>
@@ -76,7 +76,7 @@ namespace <?= $namespace === '__root' ? '' : trim($namespace, '\\') ?> {
<?php endforeach; ?> <?php endforeach; ?>
<?php foreach($real_time_facades as $name): ?> <?php foreach ($real_time_facades as $name): ?>
<?php $nested = explode('\\', str_replace('\\' . class_basename($name), '', $name)); ?> <?php $nested = explode('\\', str_replace('\\' . class_basename($name), '', $name)); ?>
namespace <?php echo implode('\\', $nested); ?> { namespace <?php echo implode('\\', $nested); ?> {
/** /**
+41
View File
@@ -21,6 +21,20 @@ namespace PHPSTORM_META {
])); ]));
<?php endforeach; ?> <?php endforeach; ?>
<?php foreach ($userMethods as $method) : ?>
override(<?= $method ?>, map([
'' => \<?= $userModel ?>::class,
]));
<?php endforeach; ?>
<?php foreach ($configMethods as $method) : ?>
override(<?= $method ?>, map([
<?php foreach ($configValues as $name => $value) : ?>
'<?= $name ?>' => '<?= $value ?>',
<?php endforeach; ?>
]));
<?php endforeach; ?>
<?php if (count($factories)) : ?> <?php if (count($factories)) : ?>
override(\factory(0), map([ override(\factory(0), map([
'' => '@FactoryBuilder', '' => '@FactoryBuilder',
@@ -65,4 +79,31 @@ namespace PHPSTORM_META {
override(\tap(0), type(0)); override(\tap(0), type(0));
override(\optional(0), type(0)); override(\optional(0), type(0));
<?php if (isset($expectedArgumentSets)): ?>
<?php foreach ($expectedArgumentSets as $name => $argumentsList) : ?>
registerArgumentsSet('<?= $name ?>', <?php foreach ($argumentsList as $i => $arg) : ?><?php if ($i % 5 == 0) {
echo "\n";
} ?><?= var_export($arg, true); ?>,<?php endforeach; ?>);
<?php endforeach; ?>
<?php endif ?>
<?php if (isset($expectedArguments)) : ?>
<?php foreach ($expectedArguments as $arguments) : ?>
<?php
$classes = isset($arguments['class']) ? (array) $arguments['class'] : [null];
$index = $arguments['index'] ?? 0;
$argumentSet = $arguments['argumentSet'];
$functions = [];
foreach ($classes as $class) {
foreach ((array) $arguments['method'] as $method) {
$functions[] = '\\' . ($class ? ltrim($class, '\\') . '::' : '') . $method . '()';
}
}
?>
<?php foreach ($functions as $function) : ?>
expectedArguments(<?= $function ?>, <?= $index ?>, argumentsSet('<?= $argumentSet ?>'));
<?php endforeach; ?>
<?php endforeach; ?>
<?php endif; ?>
} }
+90 -12
View File
@@ -13,13 +13,16 @@ namespace Barryvdh\LaravelIdeHelper;
use Barryvdh\Reflection\DocBlock; use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Context; use Barryvdh\Reflection\DocBlock\Context;
use Barryvdh\Reflection\DocBlock\ContextFactory;
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer; use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
use Barryvdh\Reflection\DocBlock\Tag\MethodTag; use Barryvdh\Reflection\DocBlock\Tag\MethodTag;
use Barryvdh\Reflection\DocBlock\Tag\TemplateTag;
use Closure; use Closure;
use Illuminate\Config\Repository as ConfigRepository; use Illuminate\Config\Repository as ConfigRepository;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Facades\Facade; use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Traits\Macroable;
use ReflectionClass; use ReflectionClass;
use Throwable; use Throwable;
@@ -34,6 +37,7 @@ class Alias
protected $classType = 'class'; protected $classType = 'class';
protected $short; protected $short;
protected $namespace = '__root'; protected $namespace = '__root';
protected $parentClass;
protected $root = null; protected $root = null;
protected $classes = []; protected $classes = [];
protected $methods = []; protected $methods = [];
@@ -47,6 +51,9 @@ class Alias
/** @var ConfigRepository */ /** @var ConfigRepository */
protected $config; protected $config;
/** @var string[] */
protected $templateNames;
/** /**
* @param ConfigRepository $config * @param ConfigRepository $config
* @param string $alias * @param string $alias
@@ -79,10 +86,11 @@ class Alias
$this->detectNamespace(); $this->detectNamespace();
$this->detectClassType(); $this->detectClassType();
$this->detectExtendsNamespace(); $this->detectExtendsNamespace();
$this->detectParentClass();
if (!empty($this->namespace)) { if (!empty($this->namespace)) {
try { try {
$this->classAliases = (new UsesResolver())->loadFromClass($this->root); $this->classAliases = (new ContextFactory())->createFromReflector(new ReflectionClass($this->root))->getNamespaceAliases();
} catch (Throwable $e) { } catch (Throwable $e) {
$this->classAliases = []; $this->classAliases = [];
} }
@@ -163,6 +171,25 @@ class Alias
return $this->extendsNamespace; return $this->extendsNamespace;
} }
/**
* Get the parent class of the class which this alias extends
*
* @return null|string
*/
public function getParentClass()
{
return $this->parentClass;
}
/**
* Check if this class should extend the parent class
*/
public function shouldExtendParentClass()
{
return $this->parentClass
&& $this->getExtendsNamespace() !== '\\Illuminate\\Support\\Facades';
}
/** /**
* Get the Alias by which this class is called * Get the Alias by which this class is called
* *
@@ -260,6 +287,18 @@ class Alias
} }
} }
/**
* Detect the parent class
*/
protected function detectParentClass()
{
$reflection = new ReflectionClass($this->root);
$parentClass = $reflection->getParentClass();
$this->parentClass = $parentClass ? '\\' . $parentClass->getName() : null;
}
/** /**
* Detect the class type * Detect the class type
*/ */
@@ -346,7 +385,8 @@ class Alias
$magic, $magic,
$this->interfaces, $this->interfaces,
$this->classAliases, $this->classAliases,
$this->getReturnTypeNormalizers($class) $this->getReturnTypeNormalizers($class),
$this->getTemplateNames()
); );
} }
$this->usedMethods[] = $magic; $this->usedMethods[] = $magic;
@@ -378,7 +418,8 @@ class Alias
$method->name, $method->name,
$this->interfaces, $this->interfaces,
$this->classAliases, $this->classAliases,
$this->getReturnTypeNormalizers($reflection) $this->getReturnTypeNormalizers($reflection),
$this->getTemplateNames(),
); );
} }
$this->usedMethods[] = $method->name; $this->usedMethods[] = $method->name;
@@ -388,15 +429,20 @@ class Alias
// Check if the class is macroable // Check if the class is macroable
// (Eloquent\Builder is also macroable but doesn't use Macroable trait) // (Eloquent\Builder is also macroable but doesn't use Macroable trait)
$traits = collect($reflection->getTraitNames()); if ($class === EloquentBuilder::class || in_array(Macroable::class, $reflection->getTraitNames())) {
if ($traits->contains('Illuminate\Support\Traits\Macroable') || $class === EloquentBuilder::class) {
$properties = $reflection->getStaticProperties(); $properties = $reflection->getStaticProperties();
$macros = isset($properties['macros']) ? $properties['macros'] : []; $macros = isset($properties['macros']) ? $properties['macros'] : [];
foreach ($macros as $macro_name => $macro_func) { foreach ($macros as $macro_name => $macro_func) {
if (!in_array($macro_name, $this->usedMethods)) { if (!in_array($macro_name, $this->usedMethods)) {
try {
$method = $this->getMacroFunction($macro_func);
} catch (Throwable $e) {
// Invalid method, skip
continue;
}
// Add macros // Add macros
$this->methods[] = new Macro( $this->methods[] = new Macro(
$this->getMacroFunction($macro_func), $method,
$this->alias, $this->alias,
$reflection, $reflection,
$macro_name, $macro_name,
@@ -476,30 +522,62 @@ class Alias
/** /**
* @param $prefix * @param $prefix
* @return string * @return string
* @throws \ReflectionException
*/ */
public function getPhpDocTemplates($prefix = "\t\t") public function getPhpDocTemplates($prefix = "\t\t")
{ {
$templateDoc = new DocBlock(''); $templateDoc = new DocBlock('');
$serializer = new DocBlockSerializer(1, $prefix); $serializer = new DocBlockSerializer(1, $prefix);
foreach ($this->getTemplateNames() as $templateName) {
$template = new TemplateTag('template', $templateName);
$template->setBound('static');
$template->setDocBlock($templateDoc);
$templateDoc->appendTag($template);
}
return $serializer->getDocComment($templateDoc);
}
/**
* @return string[]
*/
public function getTemplateNames()
{
if (!isset($this->templateNames)) {
$this->detectTemplateNames();
}
return $this->templateNames;
}
/**
* @return void
* @throws \ReflectionException
*/
protected function detectTemplateNames()
{
$templateNames = [];
foreach ($this->classes as $class) { foreach ($this->classes as $class) {
$reflection = new ReflectionClass($class); $reflection = new ReflectionClass($class);
$traits = collect($reflection->getTraitNames()); $traits = collect($reflection->getTraitNames());
$phpdoc = new DocBlock($reflection);
$templates = $phpdoc->getTagsByName('template');
/** @var TemplateTag $template */
foreach ($templates as $template) {
$templateNames[] = $template->getTemplateName();
}
foreach ($traits as $trait) { foreach ($traits as $trait) {
$phpdoc = new DocBlock(new ReflectionClass($trait)); $phpdoc = new DocBlock(new ReflectionClass($trait));
$templates = $phpdoc->getTagsByName('template'); $templates = $phpdoc->getTagsByName('template');
/** @var DocBlock\Tag\TemplateTag $template */ /** @var TemplateTag $template */
foreach ($templates as $template) { foreach ($templates as $template) {
$template->setBound('static'); $templateNames[] = $template->getTemplateName();
$template->setDocBlock($templateDoc);
$templateDoc->appendTag($template);
} }
} }
} }
return $serializer->getDocComment($templateDoc); $this->templateNames = $templateNames;
} }
/** /**
+203 -17
View File
@@ -12,10 +12,13 @@
namespace Barryvdh\LaravelIdeHelper\Console; namespace Barryvdh\LaravelIdeHelper\Console;
use Barryvdh\LaravelIdeHelper\Factories; use Barryvdh\LaravelIdeHelper\Factories;
use Dotenv\Parser\Entry;
use Dotenv\Parser\Parser;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Contracts\Config\Repository; use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Collection;
use RuntimeException; use RuntimeException;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -51,19 +54,36 @@ class MetaCommand extends Command
protected $config; protected $config;
protected $methods = [ protected $methods = [
'new \Illuminate\Contracts\Container\Container', 'new \Illuminate\Contracts\Container\Container',
'\Illuminate\Container\Container::makeWith(0)', '\Illuminate\Container\Container::makeWith(0)',
'\Illuminate\Contracts\Container\Container::get(0)', '\Illuminate\Contracts\Container\Container::get(0)',
'\Illuminate\Contracts\Container\Container::make(0)', '\Illuminate\Contracts\Container\Container::make(0)',
'\Illuminate\Contracts\Container\Container::makeWith(0)', '\Illuminate\Contracts\Container\Container::makeWith(0)',
'\App::get(0)', '\App::get(0)',
'\App::make(0)', '\App::make(0)',
'\App::makeWith(0)', '\App::makeWith(0)',
'\app(0)', '\app(0)',
'\resolve(0)', '\resolve(0)',
'\Psr\Container\ContainerInterface::get(0)', '\Psr\Container\ContainerInterface::get(0)',
]; ];
protected $configMethods = [
'\config()',
'\Illuminate\Config\Repository::get()',
'\Illuminate\Support\Facades\Config::get()',
];
protected $userMethods = [
'\auth()->user()',
'\Illuminate\Contracts\Auth\Guard::user()',
'\Illuminate\Support\Facades\Auth::user()',
'\request()->user()',
'\Illuminate\Http\Request::user()',
'\Illuminate\Support\Facades\Request::user()',
];
protected $templateCache = [];
/** /**
* *
* @param Filesystem $files * @param Filesystem $files
@@ -108,7 +128,7 @@ class MetaCommand extends Command
} }
$reflectionClass = new \ReflectionClass($concrete); $reflectionClass = new \ReflectionClass($concrete);
if (is_object($concrete) && !$reflectionClass->isAnonymous()) { if (is_object($concrete) && !$reflectionClass->isAnonymous() && $abstract !== get_class($concrete)) {
$bindings[$abstract] = get_class($concrete); $bindings[$abstract] = get_class($concrete);
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
@@ -120,10 +140,22 @@ class MetaCommand extends Command
$this->unregisterClassAutoloadExceptions($ourAutoloader); $this->unregisterClassAutoloadExceptions($ourAutoloader);
$content = $this->view->make('meta', [ $configValues = $this->loadTemplate('configs')->pluck('value', 'name')->map(function ($value, $key) {
'bindings' => $bindings, return gettype($value);
'methods' => $this->methods, });
'factories' => $factories,
$defaultUserModel = $this->config->get('auth.providers.users.model', $this->config->get('auth.model', 'App\User'));
$content = $this->view->make('ide-helper::meta', [
'bindings' => $bindings,
'methods' => $this->methods,
'factories' => $factories,
'configMethods' => $this->configMethods,
'configValues' => $configValues,
'expectedArgumentSets' => $this->getExpectedArgumentSets(),
'expectedArguments' => $this->getExpectedArguments(),
'userModel' => $defaultUserModel,
'userMethods' => $this->userMethods,
])->render(); ])->render();
$filename = $this->option('filename'); $filename = $this->option('filename');
@@ -160,13 +192,152 @@ class MetaCommand extends Command
*/ */
protected function registerClassAutoloadExceptions(): callable protected function registerClassAutoloadExceptions(): callable
{ {
$autoloader = function ($class) { $aliases = array_filter([...$this->getAbstracts(), 'config'], fn ($abstract) => !str_contains($abstract, '\\'));
$autoloader = function ($class) use ($aliases) {
// ignore aliases as they're meant to be resolved elsewhere
if (in_array($class, $aliases, true)) {
return;
}
throw new \ReflectionException("Class '$class' not found."); throw new \ReflectionException("Class '$class' not found.");
}; };
spl_autoload_register($autoloader); spl_autoload_register($autoloader);
return $autoloader; return $autoloader;
} }
protected function getExpectedArgumentSets()
{
return [
'auth' => $this->loadTemplate('auth')->keys()->filter()->toArray(),
'configs' => $this->loadTemplate('configs')->pluck('name')->filter()->toArray(),
'middleware' => $this->loadTemplate('middleware')->keys()->filter()->toArray(),
'routes' => $this->loadTemplate('routes')->pluck('name')->filter()->toArray(),
'views' => $this->loadTemplate('views')->pluck('key')->filter()->map(function ($value) {
return (string) $value;
})->toArray(),
'translations' => $this->loadTemplate('translations')->filter()->keys()->toArray(),
'env' => $this->getEnv(),
];
}
protected function getExpectedArguments()
{
return [
[
'class' => '\Illuminate\Support\Facades\Gate',
'method' => [
'has',
'allows',
'denies',
'check',
'any',
'none',
'authorize',
'inspect',
],
'argumentSet' => 'auth',
],
[
'class' => ['\Illuminate\Support\Facades\Route', '\Illuminate\Support\Facades\Auth', 'Illuminate\Foundation\Auth\Access\Authorizable'],
'method' => ['can', 'cannot', 'cant'],
'argumentSet' => 'auth',
],
[
'class' => ['Illuminate\Contracts\Auth\Access\Authorizable'],
'method' => ['can'],
'argumentSet' => 'auth',
],
[
'class' => ['\Illuminate\Config\Repository', '\Illuminate\Support\Facades\Config'],
'method' => [
// 'get', // config() and Config::Get() are added with return type hints already
'getMany',
'set',
'string',
'integer',
'boolean',
'float',
'array',
'prepend',
'push',
],
'argumentSet' => 'configs',
],
[
'class' => ['\Illuminate\Support\Facades\Route', '\Illuminate\Routing\Router'],
'method' => ['middleware', 'withoutMiddleware'],
'argumentSet' => 'middleware',
],
[
'method' => ['route', 'to_route', 'signedRoute'],
'argumentSet' => 'routes',
],
[
'class' => [
'\Illuminate\Support\Facades\Redirect',
'\Illuminate\Support\Facades\URL',
'\Illuminate\Routing\Redirector',
'\Illuminate\Routing\UrlGenerator',
],
'method' => ['route', 'signedRoute', 'temporarySignedRoute'],
'argumentSet' => 'routes',
],
[
'method' => 'view',
'argumentSet' => 'views',
],
[
'class' => ['\Illuminate\Support\Facades\View', '\Illuminate\View\Factory'],
'method' => 'make',
'argumentSet' => 'views',
],
[
'method' => ['__', 'trans'],
'argumentSet' => 'translations',
],
[
'class' => ['\Illuminate\Contracts\Translation\Translator'],
'method' => ['get'],
'argumentSet' => 'translations',
],
[
'method' => 'env',
'argumentSet' => 'env',
],
[
'class' => '\Illuminate\Support\Env',
'method' => 'get',
'argumentSet' => 'env',
],
];
}
/**
* @return Collection
*/
protected function loadTemplate($name)
{
if (!isset($this->templateCache[$name])) {
$file = __DIR__ . '/../../php-templates/' . basename($name) . '.php';
try {
$value = $this->files->requireOnce($file) ?: [];
} catch (\Throwable $e) {
$value = [];
$this->warn('Cannot load template for ' . $name . ': ' . $e->getMessage());
}
if (!$value instanceof Collection) {
$value = collect($value);
}
$this->templateCache[$name] = $value;
}
return $this->templateCache[$name];
}
/** /**
* Get the console command options. * Get the console command options.
* *
@@ -181,6 +352,21 @@ class MetaCommand extends Command
]; ];
} }
protected function getEnv()
{
$envPath = base_path('.env');
if (!file_exists($envPath)) {
return [];
}
$parser = new Parser();
$entries = $parser->parse(file_get_contents($envPath));
return collect($entries)->map(function (Entry $entry) {
return $entry->getName();
});
}
/** /**
* Remove our custom autoloader that we pushed onto the autoload stack * Remove our custom autoloader that we pushed onto the autoload stack
* *
+28 -12
View File
@@ -16,6 +16,7 @@ use Barryvdh\LaravelIdeHelper\Generator;
use Barryvdh\LaravelIdeHelper\Parsers\PhpDocReturnTypeParser; use Barryvdh\LaravelIdeHelper\Parsers\PhpDocReturnTypeParser;
use Barryvdh\Reflection\DocBlock; use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Context; use Barryvdh\Reflection\DocBlock\Context;
use Barryvdh\Reflection\DocBlock\ContextFactory;
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer; use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
use Barryvdh\Reflection\DocBlock\Tag; use Barryvdh\Reflection\DocBlock\Tag;
use Composer\ClassMapGenerator\ClassMapGenerator; use Composer\ClassMapGenerator\ClassMapGenerator;
@@ -49,7 +50,6 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\View\Factory as ViewFactory; use Illuminate\View\Factory as ViewFactory;
use phpDocumentor\Reflection\Types\ContextFactory;
use ReflectionClass; use ReflectionClass;
use ReflectionNamedType; use ReflectionNamedType;
use ReflectionObject; use ReflectionObject;
@@ -410,9 +410,6 @@ class ModelsCommand extends Command
$params = []; $params = [];
switch ($type) { switch ($type) {
case 'encrypted':
$realType = 'mixed';
break;
case 'boolean': case 'boolean':
case 'bool': case 'bool':
$realType = 'bool'; $realType = 'bool';
@@ -420,6 +417,7 @@ class ModelsCommand extends Command
case 'decimal': case 'decimal':
$realType = 'numeric'; $realType = 'numeric';
break; break;
case 'encrypted':
case 'string': case 'string':
case 'hashed': case 'hashed':
$realType = 'string'; $realType = 'string';
@@ -453,7 +451,7 @@ class ModelsCommand extends Command
$realType = '\Illuminate\Support\Collection<array-key, mixed>'; $realType = '\Illuminate\Support\Collection<array-key, mixed>';
break; break;
case AsArrayObject::class: case AsArrayObject::class:
$realType = '\ArrayObject<array-key, mixed>'; $realType = '\Illuminate\Database\Eloquent\Casts\ArrayObject<array-key, mixed>';
break; break;
default: default:
// In case of an optional custom cast parameter , only evaluate // In case of an optional custom cast parameter , only evaluate
@@ -475,7 +473,11 @@ class ModelsCommand extends Command
} }
if (Str::startsWith($type, AsCollection::class)) { if (Str::startsWith($type, AsCollection::class)) {
$realType = $this->getTypeInModel($model, $params[0] ?? null) ?? '\Illuminate\Support\Collection'; $realType = $this->getTypeInModel($model, $params[0] ?? null) ?: '\Illuminate\Support\Collection';
$relatedModel = $this->getTypeInModel($model, $params[1] ?? null);
if ($relatedModel) {
$realType = $this->getCollectionTypeHint($realType, $relatedModel);
}
} }
if (Str::startsWith($type, AsEnumCollection::class)) { if (Str::startsWith($type, AsEnumCollection::class)) {
@@ -628,6 +630,10 @@ class ModelsCommand extends Command
) )
); );
}); });
// https://github.com/barryvdh/laravel-ide-helper/issues/1664
$reflections = array_filter($reflections, function (\ReflectionMethod $methodReflection) {
return !($methodReflection->getName() === 'getUseFactoryAttribute');
});
sort($reflections); sort($reflections);
foreach ($reflections as $reflection) { foreach ($reflections as $reflection) {
$type = $this->getReturnTypeFromReflection($reflection); $type = $this->getReturnTypeFromReflection($reflection);
@@ -665,9 +671,11 @@ class ModelsCommand extends Command
$comment = $this->getCommentFromDocBlock($reflection); $comment = $this->getCommentFromDocBlock($reflection);
$this->setProperty($name, null, null, true, $comment); $this->setProperty($name, null, null, true, $comment);
} }
} elseif (Str::startsWith($method, 'scope') && $method !== 'scopeQuery' && $method !== 'scope' && $method !== 'scopes') { } elseif (!empty($reflection->getAttributes('Illuminate\Database\Eloquent\Attributes\Scope')) || (Str::startsWith($method, 'scope') && $method !== 'scopeQuery' && $method !== 'scope' && $method !== 'scopes')) {
$scopeUsingAttribute = !empty($reflection->getAttributes('Illuminate\Database\Eloquent\Attributes\Scope'));
//Magic scope<name>Attribute //Magic scope<name>Attribute
$name = Str::camel(substr($method, 5)); $name = $scopeUsingAttribute ? $method : Str::camel(substr($method, 5));
if (!empty($name)) { if (!empty($name)) {
$comment = $this->getCommentFromDocBlock($reflection); $comment = $this->getCommentFromDocBlock($reflection);
$args = $this->getParameters($reflection); $args = $this->getParameters($reflection);
@@ -819,10 +827,16 @@ class ModelsCommand extends Command
$relation === 'morphTo' $relation === 'morphTo'
) )
) { ) {
$matches = [];
$returnType = $this->getReturnTypeFromDocBlock($reflection);
if ($returnType !== null) {
preg_match('/MorphTo<(?:contravariant\s+)?(.+?)(?:,|>)/i', $returnType, $matches);
}
// Model isn't specified because relation is polymorphic // Model isn't specified because relation is polymorphic
$this->setProperty( $this->setProperty(
$method, $method,
$this->getClassNameInDestinationFile($model, Model::class) . '|\Eloquent', $matches[1] ?? $this->getClassNameInDestinationFile($model, Model::class) . '|\Eloquent',
true, true,
null, null,
$comment, $comment,
@@ -1174,7 +1188,7 @@ class ModelsCommand extends Command
$default = '[]'; $default = '[]';
} elseif (is_null($default)) { } elseif (is_null($default)) {
$default = 'null'; $default = 'null';
} elseif (is_int($default)) { } elseif (is_int($default) || is_float($default)) {
//$default = $default; //$default = $default;
} elseif ($default instanceof \UnitEnum) { } elseif ($default instanceof \UnitEnum) {
$default = '\\' . get_class($default) . '::' . $default->name; $default = '\\' . get_class($default) . '::' . $default->name;
@@ -1395,7 +1409,7 @@ class ModelsCommand extends Command
if (in_array('Illuminate\\Database\\Eloquent\\SoftDeletes', $traits)) { if (in_array('Illuminate\\Database\\Eloquent\\SoftDeletes', $traits)) {
$modelName = $this->getClassNameInDestinationFile($model, get_class($model)); $modelName = $this->getClassNameInDestinationFile($model, get_class($model));
$builder = $this->getClassNameInDestinationFile($model, \Illuminate\Database\Eloquent\Builder::class); $builder = $this->getClassNameInDestinationFile($model, \Illuminate\Database\Eloquent\Builder::class);
$this->setMethod('withTrashed', $builder . '<static>|' . $modelName, []); $this->setMethod('withTrashed', $builder . '<static>|' . $modelName, ['bool $withTrashed = true']);
$this->setMethod('withoutTrashed', $builder . '<static>|' . $modelName, []); $this->setMethod('withoutTrashed', $builder . '<static>|' . $modelName, []);
$this->setMethod('onlyTrashed', $builder . '<static>|' . $modelName, []); $this->setMethod('onlyTrashed', $builder . '<static>|' . $modelName, []);
} }
@@ -1571,7 +1585,9 @@ class ModelsCommand extends Command
*/ */
protected function getUsedClassNames(ReflectionClass $reflection): array protected function getUsedClassNames(ReflectionClass $reflection): array
{ {
$namespaceAliases = array_flip((new ContextFactory())->createFromReflector($reflection)->getNamespaceAliases()); $namespaceAliases = array_flip(array_map(function ($alias) {
return ltrim($alias, '\\');
}, (new ContextFactory())->createFromReflector($reflection)->getNamespaceAliases()));
$namespaceAliases[$reflection->getName()] = $reflection->getShortName(); $namespaceAliases[$reflection->getName()] = $reflection->getShortName();
return $namespaceAliases; return $namespaceAliases;
+41 -30
View File
@@ -17,10 +17,6 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Facade; use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Macroable;
use PhpParser\Lexer\Emulative;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Parser\Php7;
use ReflectionClass; use ReflectionClass;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -61,9 +57,13 @@ class Generator
// Find the drivers to add to the extra/interfaces // Find the drivers to add to the extra/interfaces
$this->detectDrivers(); $this->detectDrivers();
$this->extra = array_merge($this->extra, $this->config->get('ide-helper.extra'), []); $this->extra = array_merge($this->extra, $this->config->get('ide-helper.extra', []));
$this->magic = array_merge($this->magic, $this->config->get('ide-helper.magic'), []); $this->magic = array_merge($this->magic, $this->config->get('ide-helper.magic', []));
$this->interfaces = array_merge($this->interfaces, $this->config->get('ide-helper.interfaces'), []); $this->interfaces = array_merge($this->interfaces, $this->config->get('ide-helper.interfaces', []));
Macro::setDefaultReturnTypes($this->config->get('ide-helper.macro_default_return_types', [
\Illuminate\Http\Client\Factory::class => \Illuminate\Http\Client\PendingRequest::class,
]));
// Make all interface classes absolute // Make all interface classes absolute
foreach ($this->interfaces as &$interface) { foreach ($this->interfaces as &$interface) {
$interface = '\\' . ltrim($interface, '\\'); $interface = '\\' . ltrim($interface, '\\');
@@ -79,11 +79,11 @@ class Generator
public function generate() public function generate()
{ {
$app = app(); $app = app();
return $this->view->make('helper') return $this->view->make('ide-helper::helper')
->with('namespaces_by_extends_ns', $this->getAliasesByExtendsNamespace()) ->with('namespaces_by_extends_ns', $this->getAliasesByExtendsNamespace())
->with('namespaces_by_alias_ns', $this->getAliasesByAliasNamespace()) ->with('namespaces_by_alias_ns', $this->getAliasesByAliasNamespace())
->with('real_time_facades', $this->getRealTimeFacades()) ->with('real_time_facades', $this->getRealTimeFacades())
->with('helpers', $this->helpers) ->with('helpers', $this->detectHelpers())
->with('include_fluent', $this->config->get('ide-helper.include_fluent', true)) ->with('include_fluent', $this->config->get('ide-helper.include_fluent', true))
->with('factories', $this->config->get('ide-helper.include_factory_builders') ? Factories::all() : []) ->with('factories', $this->config->get('ide-helper.include_factory_builders') ? Factories::all() : [])
->render(); ->render();
@@ -105,7 +105,7 @@ class Generator
} }
$app = app(); $app = app();
return $this->view->make('helper') return $this->view->make('ide-helper::helper')
->with('namespaces_by_extends_ns', []) ->with('namespaces_by_extends_ns', [])
->with('namespaces_by_alias_ns', ['__root' => [$alias]]) ->with('namespaces_by_alias_ns', ['__root' => [$alias]])
->with('real_time_facades', []) ->with('real_time_facades', [])
@@ -115,6 +115,24 @@ class Generator
->render(); ->render();
} }
protected function detectHelpers()
{
$helpers = $this->helpers;
$replacements = [
'($guard is null ? \Illuminate\Contracts\Auth\Factory : \Illuminate\Contracts\Auth\StatefulGuard)' => '\\Auth',
];
foreach ($replacements as $search => $replace) {
$helpers = Str::replace(
"@return {$search}",
"@return $replace|$search",
$helpers
);
}
return $helpers;
}
protected function detectDrivers() protected function detectDrivers()
{ {
$defaultUserModel = config('auth.providers.users.model', config('auth.model', 'App\User')); $defaultUserModel = config('auth.providers.users.model', config('auth.model', 'App\User'));
@@ -213,8 +231,10 @@ class Generator
foreach ($realTimeFacadeFiles as $file) { foreach ($realTimeFacadeFiles as $file) {
try { try {
$name = $this->getFullyQualifiedClassNameInFile($file); $name = $this->getFullyQualifiedClassNameInFile($file);
$facades[$name] = $name; if ($name) {
} catch (\Exception $e) { $facades[$name] = $name;
}
} catch (\Throwable $e) {
continue; continue;
} }
} }
@@ -226,26 +246,17 @@ class Generator
{ {
$contents = file_get_contents($path); $contents = file_get_contents($path);
$parsers = new Php7(new Emulative()); // Match namespace
preg_match('/namespace\s+([^;]+);/', $contents, $namespaceMatch);
$namespace = isset($namespaceMatch[1]) ? $namespaceMatch[1] : '';
$parsed = collect($parsers->parse($contents) ?: []); // Match class name
preg_match('/class\s+([a-zA-Z0-9_]+)/', $contents, $classMatch);
$className = isset($classMatch[1]) ? $classMatch[1] : '';
$namespace = $parsed->first(function ($node) { // Combine namespace and class name
return $node instanceof Namespace_; if ($namespace && $className) {
}); return $namespace . '\\' . $className;
if ($namespace) {
$name = $namespace->name->toString();
$class = collect($namespace->stmts)->first(function ($node) {
return $node instanceof Class_;
});
if ($class) {
$name .= '\\' . $class->name->toString();
}
return $name;
} }
} }
-26
View File
@@ -20,10 +20,6 @@ use Illuminate\Console\Events\CommandFinished;
use Illuminate\Contracts\Support\DeferrableProvider; use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Database\Events\MigrationsEnded; use Illuminate\Database\Events\MigrationsEnded;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Illuminate\View\Engines\EngineResolver;
use Illuminate\View\Engines\PhpEngine;
use Illuminate\View\Factory;
use Illuminate\View\FileViewFinder;
class IdeHelperServiceProvider extends ServiceProvider implements DeferrableProvider class IdeHelperServiceProvider extends ServiceProvider implements DeferrableProvider
{ {
@@ -65,12 +61,6 @@ class IdeHelperServiceProvider extends ServiceProvider implements DeferrableProv
$configPath = __DIR__ . '/../config/ide-helper.php'; $configPath = __DIR__ . '/../config/ide-helper.php';
$this->mergeConfigFrom($configPath, 'ide-helper'); $this->mergeConfigFrom($configPath, 'ide-helper');
$this->app->when([GeneratorCommand::class, MetaCommand::class, ModelsCommand::class])
->needs(\Illuminate\Contracts\View\Factory::class)
->give(function () {
return $this->createLocalViewFactory();
});
$this->commands( $this->commands(
[ [
GeneratorCommand::class, GeneratorCommand::class,
@@ -95,20 +85,4 @@ class IdeHelperServiceProvider extends ServiceProvider implements DeferrableProv
EloquentCommand::class, EloquentCommand::class,
]; ];
} }
/**
* @return Factory
*/
private function createLocalViewFactory()
{
$resolver = new EngineResolver();
$resolver->register('php', function () {
return new PhpEngine($this->app['files']);
});
$finder = new FileViewFinder($this->app['files'], [__DIR__ . '/../resources/views']);
$factory = new Factory($resolver, $finder, $this->app['events']);
$factory->addExtension('php', 'php');
return $factory;
}
} }
+12
View File
@@ -9,6 +9,8 @@ use Illuminate\Support\Collection;
class Macro extends Method class Macro extends Method
{ {
protected static $macroDefaults = [];
/** /**
* Macro constructor. * Macro constructor.
* *
@@ -32,6 +34,10 @@ class Macro extends Method
parent::__construct($method, $alias, $class, $methodName, $interfaces, $classAliases, $returnTypeNormalizers); parent::__construct($method, $alias, $class, $methodName, $interfaces, $classAliases, $returnTypeNormalizers);
} }
public static function setDefaultReturnTypes(array $map = [])
{
static::$macroDefaults = array_merge(static::$macroDefaults, $map);
}
/** /**
* @param \ReflectionFunctionAbstract $method * @param \ReflectionFunctionAbstract $method
*/ */
@@ -77,6 +83,12 @@ class Macro extends Method
$this->phpdoc->appendTag(Tag::createInstance("@return {$type}")); $this->phpdoc->appendTag(Tag::createInstance("@return {$type}"));
} }
$class = ltrim($this->declaringClassName, '\\');
if (!$this->phpdoc->hasTag('return') && isset(static::$macroDefaults[$class])) {
$type = static::$macroDefaults[$class];
$this->phpdoc->appendTag(Tag::createInstance("@return {$type}"));
}
} }
protected function concatReflectionTypes(?\ReflectionType $type): string protected function concatReflectionTypes(?\ReflectionType $type): string
+8 -3
View File
@@ -39,6 +39,9 @@ class Method
protected $classAliases; protected $classAliases;
protected $returnTypeNormalizers; protected $returnTypeNormalizers;
/** @var string[] */
protected $templateNames = [];
/** /**
* @param \ReflectionMethod|\ReflectionFunctionAbstract $method * @param \ReflectionMethod|\ReflectionFunctionAbstract $method
* @param string $alias * @param string $alias
@@ -47,8 +50,9 @@ class Method
* @param array $interfaces * @param array $interfaces
* @param array $classAliases * @param array $classAliases
* @param array $returnTypeNormalizers * @param array $returnTypeNormalizers
* @param string[] $templateNames
*/ */
public function __construct($method, $alias, $class, $methodName = null, $interfaces = [], array $classAliases = [], array $returnTypeNormalizers = []) public function __construct($method, $alias, $class, $methodName = null, $interfaces = [], array $classAliases = [], array $returnTypeNormalizers = [], array $templateNames = [])
{ {
$this->method = $method; $this->method = $method;
$this->interfaces = $interfaces; $this->interfaces = $interfaces;
@@ -56,6 +60,7 @@ class Method
$this->returnTypeNormalizers = $returnTypeNormalizers; $this->returnTypeNormalizers = $returnTypeNormalizers;
$this->name = $methodName ?: $method->name; $this->name = $methodName ?: $method->name;
$this->real_name = $method->isClosure() ? $this->name : $method->name; $this->real_name = $method->isClosure() ? $this->name : $method->name;
$this->templateNames = $templateNames;
$this->initClassDefinedProperties($method, $class); $this->initClassDefinedProperties($method, $class);
//Reference the 'real' function in the declaring class //Reference the 'real' function in the declaring class
@@ -84,7 +89,7 @@ class Method
*/ */
protected function initPhpDoc($method) protected function initPhpDoc($method)
{ {
$this->phpdoc = new DocBlock($method, new Context($this->namespace, $this->classAliases)); $this->phpdoc = new DocBlock($method, new Context($this->namespace, $this->classAliases, generics: $this->templateNames));
} }
/** /**
@@ -386,7 +391,7 @@ class Method
} }
if ($method) { if ($method) {
$namespace = $method->getDeclaringClass()->getNamespaceName(); $namespace = $method->getDeclaringClass()->getNamespaceName();
$phpdoc = new DocBlock($method, new Context($namespace, $this->classAliases)); $phpdoc = new DocBlock($method, new Context($namespace, $this->classAliases, generics: $this->templateNames));
if (strpos($phpdoc->getText(), '{@inheritdoc}') !== false) { if (strpos($phpdoc->getText(), '{@inheritdoc}') !== false) {
//Not at the end yet, try another parent/interface.. //Not at the end yet, try another parent/interface..
-124
View File
@@ -1,124 +0,0 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <barryvdh@gmail.com>
* @copyright 2014 Barry vd. Heuvel / Fruitcake Studio (http://www.fruitcakestudio.nl)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link https://github.com/barryvdh/laravel-ide-helper
*/
namespace Barryvdh\LaravelIdeHelper;
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use PhpParser\ParserFactory;
class UsesResolver
{
/**
* @param string $classFQN
* @return array
*/
public function loadFromClass(string $classFQN): array
{
return $this->loadFromFile(
$classFQN,
(new \ReflectionClass($classFQN))->getFileName()
);
}
/**
* @param string $classFQN
* @param string $filename
* @return array
*/
public function loadFromFile(string $classFQN, string $filename): array
{
return $this->loadFromCode(
$classFQN,
file_get_contents(
$filename
)
);
}
/**
* @param string $classFQN
* @param string $code
* @return array
*/
public function loadFromCode(string $classFQN, string $code): array
{
$classFQN = ltrim($classFQN, '\\');
$namespace = rtrim(
preg_replace(
'/([^\\\\]+)$/',
'',
$classFQN
),
'\\'
);
$parser = (new ParserFactory())->createForHostVersion();
$namespaceData = null;
foreach ($parser->parse($code) as $node) {
if ($node instanceof Namespace_ && $node->name->toCodeString() === $namespace) {
$namespaceData = $node;
break;
}
}
if ($namespaceData === null) {
return [];
}
/** @var Namespace_ $namespaceData */
$aliases = [];
foreach ($namespaceData->stmts as $stmt) {
if ($stmt instanceof Use_) {
if ($stmt->type !== Use_::TYPE_NORMAL) {
continue;
}
foreach ($stmt->uses as $use) {
/** @var UseUse $use */
$alias = $use->alias ?
$use->alias->name :
self::classBasename($use->name->toCodeString());
$aliases[$alias] = '\\' . $use->name->toCodeString();
}
} elseif ($stmt instanceof GroupUse) {
foreach ($stmt->uses as $use) {
/** @var UseUse $use */
$alias = $use->alias ?
$use->alias->name :
self::classBasename($use->name->toCodeString());
$aliases[$alias] = '\\' . $stmt->prefix->toCodeString() . '\\' . $use->name->toCodeString();
}
}
}
return $aliases;
}
/**
* @param string $classFQN
* @return string
*/
protected static function classBasename(string $classFQN): string
{
return preg_replace('/^.*\\\\([^\\\\]+)$/', '$1', $classFQN);
}
}
+16
View File
@@ -66,6 +66,21 @@ class AliasTest extends TestCase
$this->assertNotNull($this->getAliasMacro($alias, EloquentBuilder::class, $macro)); $this->assertNotNull($this->getAliasMacro($alias, EloquentBuilder::class, $macro));
} }
/**
* @covers ::detectTemplateNames
*/
public function testTemplateNamesAreDetected(): void
{
// Mock
$alias = new AliasMock();
// Prepare
$alias->setClasses([EloquentBuilder::class]);
// Test
$this->assertSame(['TModel', 'TValue'], $alias->getTemplateNames());
}
protected function getAliasMacro(Alias $alias, string $class, string $method): ?Macro protected function getAliasMacro(Alias $alias, string $class, string $method): ?Macro
{ {
return Arr::first( return Arr::first(
@@ -82,6 +97,7 @@ class AliasTest extends TestCase
/** /**
* @internal * @internal
* @noinspection PhpMultipleClassesDeclarationsInOneFile * @noinspection PhpMultipleClassesDeclarationsInOneFile
* @template TValue
*/ */
class AliasMock extends Alias class AliasMock extends Alias
{ {
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\GeneratorCommand; namespace Barryvdh\LaravelIdeHelper\Tests\Console\GeneratorCommand;
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider; use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
use Barryvdh\LaravelIdeHelper\Tests\SnapshotPhpDriver;
use Barryvdh\LaravelIdeHelper\Tests\TestCase; use Barryvdh\LaravelIdeHelper\Tests\TestCase;
abstract class AbstractGeneratorCommand extends TestCase abstract class AbstractGeneratorCommand extends TestCase
@@ -27,9 +26,4 @@ abstract class AbstractGeneratorCommand extends TestCase
{ {
return [IdeHelperServiceProvider::class]; return [IdeHelperServiceProvider::class];
} }
protected function assertMatchesMockedSnapshot()
{
$this->assertMatchesSnapshot($this->mockFilesystemOutput, new SnapshotPhpDriver());
}
} }
@@ -6,18 +6,30 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\GeneratorCommand\GenerateIdeHe
use Barryvdh\LaravelIdeHelper\Console\GeneratorCommand; use Barryvdh\LaravelIdeHelper\Console\GeneratorCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\GeneratorCommand\AbstractGeneratorCommand; use Barryvdh\LaravelIdeHelper\Tests\Console\GeneratorCommand\AbstractGeneratorCommand;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
class Test extends AbstractGeneratorCommand class Test extends AbstractGeneratorCommand
{ {
public function testGenerator(): void public function testGenerator(): void
{ {
Arr::macro('arr_custom_macro', function () {
});
DB::macro('db_custom_macro', function () {
});
$this->app['config']->set('ide-helper.macro_default_return_types', [Arr::class => 'Custom_Fake_Class']);
$command = $this->app->make(GeneratorCommand::class); $command = $this->app->make(GeneratorCommand::class);
$tester = $this->runCommand($command); $tester = $this->runCommand($command);
$this->assertSame(0, $tester->getStatusCode()); $this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('A new helper file was written to _ide_helper.php', $tester->getDisplay()); $this->assertStringContainsString('A new helper file was written to _ide_helper.php', $tester->getDisplay());
$this->assertStringContainsString('public static function configure($basePath = null)', $this->mockFilesystemOutput); $this->assertStringContainsString('public static function configure($basePath = null)', $this->mockFilesystemOutput);
$this->assertStringContainsString('* @return \Custom_Fake_Class', $this->mockFilesystemOutput);
$this->assertStringContainsString('public static function arr_custom_macro()', $this->mockFilesystemOutput);
$this->assertStringContainsString('public static function db_custom_macro()', $this->mockFilesystemOutput);
} }
public function testFilename(): void public function testFilename(): void
@@ -27,7 +27,7 @@ class MetaCommandTest extends TestCase
$mockFileSystem $mockFileSystem
->shouldReceive('getRequire') ->shouldReceive('getRequire')
->andReturnUsing(function ($__path, $__data) { ->andReturnUsing(function ($__path, $__data = []) {
return (static function () use ($__path, $__data) { return (static function () use ($__path, $__data) {
extract($__data, EXTR_SKIP); extract($__data, EXTR_SKIP);
@@ -60,7 +60,7 @@ class MetaCommandTest extends TestCase
$mockFileSystem $mockFileSystem
->shouldReceive('getRequire') ->shouldReceive('getRequire')
->andReturnUsing(function ($__path, $__data) { ->andReturnUsing(function ($__path, $__data = []) {
return (static function () use ($__path, $__data) { return (static function () use ($__path, $__data) {
extract($__data, EXTR_SKIP); extract($__data, EXTR_SKIP);
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand; namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider; use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
use Barryvdh\LaravelIdeHelper\Tests\SnapshotPhpDriver;
use Barryvdh\LaravelIdeHelper\Tests\TestCase; use Barryvdh\LaravelIdeHelper\Tests\TestCase;
abstract class AbstractModelsCommand extends TestCase abstract class AbstractModelsCommand extends TestCase
@@ -52,9 +51,4 @@ abstract class AbstractModelsCommand extends TestCase
// Don't override integer -> int for tests // Don't override integer -> int for tests
$config->set('ide-helper.type_overrides', []); $config->set('ide-helper.type_overrides', []);
} }
protected function assertMatchesMockedSnapshot()
{
$this->assertMatchesSnapshot($this->mockFilesystemOutput, new SnapshotPhpDriver());
}
} }
@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections;
use Illuminate\Contracts\Support\Arrayable;
use JsonSerializable;
class AdvancedCastMap implements Arrayable, JsonSerializable
{
public function toArray(): array
{
return [];
}
public function jsonSerialize(): array
{
return $this->toArray();
}
}
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Models; namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections\AdvancedCastCollection; use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections\AdvancedCastCollection;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections\AdvancedCastMap;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Enums\AdvancedCastEnum; use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Enums\AdvancedCastEnum;
use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Casts\AsCollection; use Illuminate\Database\Eloquent\Casts\AsCollection;
@@ -29,7 +30,9 @@ class AdvancedCast extends Model
'cast_to_encrypted_json' => 'encrypted:json', 'cast_to_encrypted_json' => 'encrypted:json',
'cast_to_encrypted_object' => 'encrypted:object', 'cast_to_encrypted_object' => 'encrypted:object',
'cast_to_as_collection' => AsCollection::class, 'cast_to_as_collection' => AsCollection::class,
'cast_to_as_collection_of' => AsCollection::class . ':,' . AdvancedCastMap::class, // since 12.10
'cast_to_as_collection_using' => AsCollection::using(AdvancedCastCollection::class), 'cast_to_as_collection_using' => AsCollection::using(AdvancedCastCollection::class),
'cast_to_as_collection_using_and_map' => AsCollection::class . ':' . AdvancedCastCollection::class . ',' . AdvancedCastMap::class, // since 12.10
'cast_to_as_enum_collection' => AsEnumCollection::class, 'cast_to_as_enum_collection' => AsEnumCollection::class,
'cast_to_as_enum_collection_of' => AsEnumCollection::of(AdvancedCastEnum::class), 'cast_to_as_enum_collection_of' => AsEnumCollection::of(AdvancedCastEnum::class),
'cast_to_as_array_object' => AsArrayObject::class, 'cast_to_as_array_object' => AsArrayObject::class,
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Models; namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections\AdvancedCastCollection; use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections\AdvancedCastCollection;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections\AdvancedCastMap;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Enums\AdvancedCastEnum; use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Enums\AdvancedCastEnum;
use Illuminate\Database\Eloquent\Casts\AsArrayObject; use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Casts\AsCollection; use Illuminate\Database\Eloquent\Casts\AsCollection;
@@ -12,8 +13,6 @@ use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property \Illuminate\Support\Carbon $cast_to_date_serialization * @property \Illuminate\Support\Carbon $cast_to_date_serialization
* @property \Illuminate\Support\Carbon $cast_to_datetime_serialization * @property \Illuminate\Support\Carbon $cast_to_datetime_serialization
* @property \Illuminate\Support\Carbon $cast_to_custom_datetime * @property \Illuminate\Support\Carbon $cast_to_custom_datetime
@@ -21,15 +20,17 @@ use Illuminate\Database\Eloquent\Model;
* @property \Carbon\CarbonImmutable $cast_to_immutable_custom_datetime * @property \Carbon\CarbonImmutable $cast_to_immutable_custom_datetime
* @property \Carbon\CarbonImmutable $cast_to_immutable_datetime * @property \Carbon\CarbonImmutable $cast_to_immutable_datetime
* @property int $cast_to_timestamp * @property int $cast_to_timestamp
* @property mixed $cast_to_encrypted * @property string $cast_to_encrypted
* @property array<array-key, mixed> $cast_to_encrypted_array * @property array<array-key, mixed> $cast_to_encrypted_array
* @property \Illuminate\Support\Collection<array-key, mixed> $cast_to_encrypted_collection * @property \Illuminate\Support\Collection<array-key, mixed> $cast_to_encrypted_collection
* @property array<array-key, mixed> $cast_to_encrypted_json * @property array<array-key, mixed> $cast_to_encrypted_json
* @property object $cast_to_encrypted_object * @property object $cast_to_encrypted_object
* @property \Illuminate\Support\Collection $cast_to_as_collection * @property \Illuminate\Support\Collection $cast_to_as_collection
* @property \Illuminate\Support\Collection $cast_to_as_enum_collection * @property \Illuminate\Support\Collection $cast_to_as_enum_collection
* @property \ArrayObject<array-key, mixed> $cast_to_as_array_object * @property \Illuminate\Database\Eloquent\Casts\ArrayObject<array-key, mixed> $cast_to_as_array_object
* @property \Illuminate\Support\Collection<int, AdvancedCastMap> $cast_to_as_collection_of
* @property AdvancedCastCollection $cast_to_as_collection_using * @property AdvancedCastCollection $cast_to_as_collection_using
* @property AdvancedCastCollection<int, AdvancedCastMap> $cast_to_as_collection_using_and_map
* @property \Illuminate\Support\Collection<int, AdvancedCastEnum> $cast_to_as_enum_collection_of * @property \Illuminate\Support\Collection<int, AdvancedCastEnum> $cast_to_as_enum_collection_of
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast newQuery()
@@ -69,7 +70,9 @@ class AdvancedCast extends Model
'cast_to_encrypted_json' => 'encrypted:json', 'cast_to_encrypted_json' => 'encrypted:json',
'cast_to_encrypted_object' => 'encrypted:object', 'cast_to_encrypted_object' => 'encrypted:object',
'cast_to_as_collection' => AsCollection::class, 'cast_to_as_collection' => AsCollection::class,
'cast_to_as_collection_of' => AsCollection::class . ':,' . AdvancedCastMap::class, // since 12.10
'cast_to_as_collection_using' => AsCollection::using(AdvancedCastCollection::class), 'cast_to_as_collection_using' => AsCollection::using(AdvancedCastCollection::class),
'cast_to_as_collection_using_and_map' => AsCollection::class . ':' . AdvancedCastCollection::class . ',' . AdvancedCastMap::class, // since 12.10
'cast_to_as_enum_collection' => AsEnumCollection::class, 'cast_to_as_enum_collection' => AsEnumCollection::class,
'cast_to_as_enum_collection_of' => AsEnumCollection::of(AdvancedCastEnum::class), 'cast_to_as_enum_collection_of' => AsEnumCollection::of(AdvancedCastEnum::class),
'cast_to_as_array_object' => AsArrayObject::class, 'cast_to_as_array_object' => AsArrayObject::class,
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AllowGlobDirecto
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ArrayCastsWithCo
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property array<int, string>|null $cast_to_array -- These three should not be duplicated * @property array<int, string>|null $cast_to_array -- These three should not be duplicated
* @property array<int, string> $cast_to_json some-description * @property array<int, string> $cast_to_json some-description
* @property \Illuminate\Support\Collection<int, string> $cast_to_collection some-description * @property \Illuminate\Support\Collection<int, string> $cast_to_collection some-description
@@ -8,8 +8,6 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $name * @property string|null $name
* @property string|null $name_read * @property string|null $name_read
@@ -85,8 +83,6 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property int $diverging_type_hinted_get_and_set * @property int $diverging_type_hinted_get_and_set
* @property string|null $name * @property string|null $name
@@ -10,8 +10,6 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo;
/** /**
*
*
* @property int $id * @property int $id
* @property string $both_same_name I'm a getter * @property string $both_same_name I'm a getter
* @property string $both_without_getter_comment * @property string $both_without_getter_comment
@@ -9,8 +9,6 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
/** /**
*
*
* @property int $id * @property int $id
* @property-read SimpleCollection<int, Simple> $relationHasMany * @property-read SimpleCollection<int, Simple> $relationHasMany
* @property-read int|null $relation_has_many_count * @property-read int|null $relation_has_many_count
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomDate\Model
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property \Carbon\CarbonImmutable|null $created_at * @property \Carbon\CarbonImmutable|null $created_at
* @property \Carbon\CarbonImmutable|null $updated_at * @property \Carbon\CarbonImmutable|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomDate newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|CustomDate newModelQuery()
@@ -13,8 +13,6 @@
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Models{ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Models{
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -10,8 +10,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
/** /**
*
*
* @property-read \Illuminate\Database\Eloquent\Collection<int, Dynamic> $regularHasMany * @property-read \Illuminate\Database\Eloquent\Collection<int, Dynamic> $regularHasMany
* @property-read int|null $regular_has_many_count * @property-read int|null $regular_has_many_count
* @method static \Illuminate\Database\Eloquent\Builder<static>|Dynamic newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|Dynamic newModelQuery()
@@ -9,8 +9,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\CustomSpace\ModelWithCustomNamespaceFactory factory($count = null, $state = []) * @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\CustomSpace\ModelWithCustomNamespaceFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithCustomNamespace newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithCustomNamespace newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithCustomNamespace newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithCustomNamespace newQuery()
@@ -41,8 +39,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Factories\ModelWithFactoryFactory factory($count = null, $state = []) * @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Factories\ModelWithFactoryFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithFactory newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithFactory newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithFactory newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithFactory newQuery()
@@ -60,8 +56,6 @@ declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models; namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
/** /**
*
*
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Factories\ModelWithNestedFactoryFactory factory($count = null, $state = []) * @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Factories\ModelWithNestedFactoryFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithNestedFactory newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithNestedFactory newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithNestedFactory newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithNestedFactory newQuery()
@@ -81,8 +75,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory query() * @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory query()
@@ -9,8 +9,6 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhp
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhp
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $charNullable * @property string|null $charNullable
* @property string $charNotNullable * @property string $charNotNullable
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhp
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -67,8 +67,6 @@ class WithCollection extends Model
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\Models{ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\Models{
/** /**
*
*
* @property-read \Illuminate\Support\Collection<int, string> $collection * @property-read \Illuminate\Support\Collection<int, string> $collection
* @property-read \Illuminate\Support\Collection<\Illuminate\Support\Collection, \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\NonModels\CollectionModel<\Illuminate\Support\Collection, \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\NonModels\CollectionModel<int, \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\NonModels\NonModel>>> $collection_with_nested_template * @property-read \Illuminate\Support\Collection<\Illuminate\Support\Collection, \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\NonModels\CollectionModel<\Illuminate\Support\Collection, \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\NonModels\CollectionModel<int, \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\NonModels\NonModel>>> $collection_with_nested_template
* @property-read \Illuminate\Support\Collection<int, \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\NonModels\NonModel> $collection_with_non_model_template * @property-read \Illuminate\Support\Collection<int, \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateMixinCollection\NonModels\NonModel> $collection_with_non_model_template
@@ -0,0 +1,251 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpDocWithTypedScopeParameter\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* @comment Scope with required boolean parameter
*/
protected function scopeTyped01(Builder $query, bool $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional boolean parameter and default true
*/
protected function scopeTyped02(Builder $query, bool $value = true)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional boolean parameter and default false
*/
protected function scopeTyped03(Builder $query, bool $value = false)
{
$query->where('type', $value);
}
/**
* @comment Scope with required string parameter
*/
protected function scopeTyped04(Builder $query, string $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional string parameter and default value
*/
protected function scopeTyped05(Builder $query, string $value = 'dummy123')
{
$query->where('type', $value);
}
/**
* @comment Scope with required integer parameter
*/
protected function scopeTyped06(Builder $query, int $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional integer parameter and default positive value
*/
protected function scopeTyped07(Builder $query, int $value = 123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional integer parameter and default negative value
*/
protected function scopeTyped08(Builder $query, int $value = -123)
{
$query->where('type', $value);
}
/**
* @comment Scope with required float parameter
*/
protected function scopeTyped09(Builder $query, float $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default positive integer value
*/
protected function scopeTyped10(Builder $query, float $value = 123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default negative integer value
*/
protected function scopeTyped11(Builder $query, float $value = -123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default positive float value
*/
protected function scopeTyped12(Builder $query, float $value = 1.23)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default negative float value
*/
protected function scopeTyped13(Builder $query, float $value = -1.23)
{
$query->where('type', $value);
}
/**
* @comment Scope with required nullable boolean parameter
*/
protected function scopeTyped14(Builder $query, ?bool $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable boolean parameter and default true
*/
protected function scopeTyped15(Builder $query, ?bool $value = true)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable boolean parameter and default false
*/
protected function scopeTyped16(Builder $query, ?bool $value = false)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable boolean parameter and default null
*/
protected function scopeTyped17(Builder $query, ?bool $value = null)
{
$query->where('type', $value);
}
/**
* @comment Scope with required nullable string parameter
*/
protected function scopeTyped18(Builder $query, ?string $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable string parameter and default value
*/
protected function scopeTyped19(Builder $query, ?string $value = 'dummy123')
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable string parameter and default null
*/
protected function scopeTyped20(Builder $query, ?string $value = null)
{
$query->where('type', $value);
}
/**
* @comment Scope with required nullable integer parameter
*/
protected function scopeTyped21(Builder $query, ?int $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable integer parameter and default positive value
*/
protected function scopeTyped22(Builder $query, ?int $value = 123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable integer parameter and default negative value
*/
protected function scopeTyped23(Builder $query, ?int $value = -123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable integer parameter and default null
*/
protected function scopeTyped24(Builder $query, ?int $value = null)
{
$query->where('type', $value);
}
/**
* @comment Scope with required float nullable parameter
*/
protected function scopeTyped25(Builder $query, ?float $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable float parameter and default positive integer value
*/
protected function scopeTyped26(Builder $query, ?float $value = 123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable float parameter and default negative integer value
*/
protected function scopeTyped27(Builder $query, ?float $value = -123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default positive float value
*/
protected function scopeTyped28(Builder $query, ?float $value = 1.23)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default negative float value
*/
protected function scopeTyped29(Builder $query, ?float $value = -1.23)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default null
*/
protected function scopeTyped30(Builder $query, ?float $value = null)
{
$query->where('type', $value);
}
}
@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpDocWithTypedScopeParameter;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -0,0 +1,287 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpDocWithTypedScopeParameter\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
* @method static Builder<static>|Comment newModelQuery()
* @method static Builder<static>|Comment newQuery()
* @method static Builder<static>|Comment query()
* @method static Builder<static>|Comment typed01(bool $value) Scope with required boolean parameter
* @method static Builder<static>|Comment typed02(bool $value = true) Scope with optional boolean parameter and default true
* @method static Builder<static>|Comment typed03(bool $value = false) Scope with optional boolean parameter and default false
* @method static Builder<static>|Comment typed04(string $value) Scope with required string parameter
* @method static Builder<static>|Comment typed05(string $value = 'dummy123') Scope with optional string parameter and default value
* @method static Builder<static>|Comment typed06(int $value) Scope with required integer parameter
* @method static Builder<static>|Comment typed07(int $value = 123) Scope with optional integer parameter and default positive value
* @method static Builder<static>|Comment typed08(int $value = -123) Scope with optional integer parameter and default negative value
* @method static Builder<static>|Comment typed09(float $value) Scope with required float parameter
* @method static Builder<static>|Comment typed10(float $value = 123) Scope with optional float parameter and default positive integer value
* @method static Builder<static>|Comment typed11(float $value = -123) Scope with optional float parameter and default negative integer value
* @method static Builder<static>|Comment typed12(float $value = 1.23) Scope with optional float parameter and default positive float value
* @method static Builder<static>|Comment typed13(float $value = -1.23) Scope with optional float parameter and default negative float value
* @method static Builder<static>|Comment typed14(?bool $value) Scope with required nullable boolean parameter
* @method static Builder<static>|Comment typed15(?bool $value = true) Scope with optional nullable boolean parameter and default true
* @method static Builder<static>|Comment typed16(?bool $value = false) Scope with optional nullable boolean parameter and default false
* @method static Builder<static>|Comment typed17(?bool $value = null) Scope with optional nullable boolean parameter and default null
* @method static Builder<static>|Comment typed18(?string $value) Scope with required nullable string parameter
* @method static Builder<static>|Comment typed19(?string $value = 'dummy123') Scope with optional nullable string parameter and default value
* @method static Builder<static>|Comment typed20(?string $value = null) Scope with optional nullable string parameter and default null
* @method static Builder<static>|Comment typed21(?int $value) Scope with required nullable integer parameter
* @method static Builder<static>|Comment typed22(?int $value = 123) Scope with optional nullable integer parameter and default positive value
* @method static Builder<static>|Comment typed23(?int $value = -123) Scope with optional nullable integer parameter and default negative value
* @method static Builder<static>|Comment typed24(?int $value = null) Scope with optional nullable integer parameter and default null
* @method static Builder<static>|Comment typed25(?float $value) Scope with required float nullable parameter
* @method static Builder<static>|Comment typed26(?float $value = 123) Scope with optional nullable float parameter and default positive integer value
* @method static Builder<static>|Comment typed27(?float $value = -123) Scope with optional nullable float parameter and default negative integer value
* @method static Builder<static>|Comment typed28(?float $value = 1.23) Scope with optional float parameter and default positive float value
* @method static Builder<static>|Comment typed29(?float $value = -1.23) Scope with optional float parameter and default negative float value
* @method static Builder<static>|Comment typed30(?float $value = null) Scope with optional float parameter and default null
* @mixin \Eloquent
*/
class Comment extends Model
{
/**
* @comment Scope with required boolean parameter
*/
protected function scopeTyped01(Builder $query, bool $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional boolean parameter and default true
*/
protected function scopeTyped02(Builder $query, bool $value = true)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional boolean parameter and default false
*/
protected function scopeTyped03(Builder $query, bool $value = false)
{
$query->where('type', $value);
}
/**
* @comment Scope with required string parameter
*/
protected function scopeTyped04(Builder $query, string $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional string parameter and default value
*/
protected function scopeTyped05(Builder $query, string $value = 'dummy123')
{
$query->where('type', $value);
}
/**
* @comment Scope with required integer parameter
*/
protected function scopeTyped06(Builder $query, int $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional integer parameter and default positive value
*/
protected function scopeTyped07(Builder $query, int $value = 123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional integer parameter and default negative value
*/
protected function scopeTyped08(Builder $query, int $value = -123)
{
$query->where('type', $value);
}
/**
* @comment Scope with required float parameter
*/
protected function scopeTyped09(Builder $query, float $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default positive integer value
*/
protected function scopeTyped10(Builder $query, float $value = 123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default negative integer value
*/
protected function scopeTyped11(Builder $query, float $value = -123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default positive float value
*/
protected function scopeTyped12(Builder $query, float $value = 1.23)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default negative float value
*/
protected function scopeTyped13(Builder $query, float $value = -1.23)
{
$query->where('type', $value);
}
/**
* @comment Scope with required nullable boolean parameter
*/
protected function scopeTyped14(Builder $query, ?bool $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable boolean parameter and default true
*/
protected function scopeTyped15(Builder $query, ?bool $value = true)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable boolean parameter and default false
*/
protected function scopeTyped16(Builder $query, ?bool $value = false)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable boolean parameter and default null
*/
protected function scopeTyped17(Builder $query, ?bool $value = null)
{
$query->where('type', $value);
}
/**
* @comment Scope with required nullable string parameter
*/
protected function scopeTyped18(Builder $query, ?string $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable string parameter and default value
*/
protected function scopeTyped19(Builder $query, ?string $value = 'dummy123')
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable string parameter and default null
*/
protected function scopeTyped20(Builder $query, ?string $value = null)
{
$query->where('type', $value);
}
/**
* @comment Scope with required nullable integer parameter
*/
protected function scopeTyped21(Builder $query, ?int $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable integer parameter and default positive value
*/
protected function scopeTyped22(Builder $query, ?int $value = 123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable integer parameter and default negative value
*/
protected function scopeTyped23(Builder $query, ?int $value = -123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable integer parameter and default null
*/
protected function scopeTyped24(Builder $query, ?int $value = null)
{
$query->where('type', $value);
}
/**
* @comment Scope with required float nullable parameter
*/
protected function scopeTyped25(Builder $query, ?float $value)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable float parameter and default positive integer value
*/
protected function scopeTyped26(Builder $query, ?float $value = 123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional nullable float parameter and default negative integer value
*/
protected function scopeTyped27(Builder $query, ?float $value = -123)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default positive float value
*/
protected function scopeTyped28(Builder $query, ?float $value = 1.23)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default negative float value
*/
protected function scopeTyped29(Builder $query, ?float $value = -1.23)
{
$query->where('type', $value);
}
/**
* @comment Scope with optional float parameter and default null
*/
protected function scopeTyped30(Builder $query, ?float $value = null)
{
$query->where('type', $value);
}
}
@@ -13,8 +13,6 @@
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithExternalEloquentBuilder\Models{ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithExternalEloquentBuilder\Models{
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -8,8 +8,6 @@ use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithExte
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -9,8 +9,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -160,7 +158,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post whereUuidNullable($value) * @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post whereUuidNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post whereYearNotNullable($value) * @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post whereYearNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post whereYearNullable($value) * @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post whereYearNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post withTrashed() * @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post withTrashed(bool $withTrashed = true)
* @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post withoutTrashed() * @method static \Illuminate\Database\Eloquent\Builder<static>|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithForcedFqn\Models\Post withoutTrashed()
* @mixin \Eloquent * @mixin \Eloquent
*/ */
@@ -15,8 +15,6 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property CastType $char_not_nullable * @property CastType $char_not_nullable
@@ -166,7 +164,7 @@ use Illuminate\Support\Carbon;
* @method static EloquentBuilder<static>|Post whereUuidNullable($value) * @method static EloquentBuilder<static>|Post whereUuidNullable($value)
* @method static EloquentBuilder<static>|Post whereYearNotNullable($value) * @method static EloquentBuilder<static>|Post whereYearNotNullable($value)
* @method static EloquentBuilder<static>|Post whereYearNullable($value) * @method static EloquentBuilder<static>|Post whereYearNullable($value)
* @method static EloquentBuilder<static>|Post withTrashed() * @method static EloquentBuilder<static>|Post withTrashed(bool $withTrashed = true)
* @method static EloquentBuilder<static>|Post withoutTrashed() * @method static EloquentBuilder<static>|Post withoutTrashed()
* @mixin Eloquent * @mixin Eloquent
*/ */
@@ -13,8 +13,6 @@
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithFqnInExternalFile\Models{ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithFqnInExternalFile\Models{
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -45,8 +45,6 @@ class Post extends Model
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithMixin\Models{ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithMixin\Models{
/** /**
*
*
* @property $someProp * @property $someProp
* @method someMethod(string $method) * @method someMethod(string $method)
* @method static \Illuminate\Database\Eloquent\Builder<static>|FinalPost newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|FinalPost newModelQuery()
@@ -60,8 +58,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWi
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithMixin\Models{ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithMixin\Models{
/** /**
*
*
* @property $someProp * @property $someProp
* @method someMethod(string $method) * @method someMethod(string $method)
* @property int $id * @property int $id
@@ -9,8 +9,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
/** /**
*
*
* @property int $id * @property int $id
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $regularBelongsToMany * @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $regularBelongsToMany
* @property-read int|null $regular_belongs_to_many_count * @property-read int|null $regular_belongs_to_many_count
@@ -8,8 +8,6 @@ use DateTime;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property-read int|null $attribute_return_type_int_or_null * @property-read int|null $attribute_return_type_int_or_null
* @property-read array $attribute_returns_array * @property-read array $attribute_returns_array
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Ignored\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|NotIgnored newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|NotIgnored newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|NotIgnored newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|NotIgnored newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|NotIgnored query() * @method static \Illuminate\Database\Eloquent\Builder<static>|NotIgnored query()
@@ -13,8 +13,6 @@
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Interfaces\Models{ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Interfaces\Models{
/** /**
*
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|User newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|User newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User query() * @method static \Illuminate\Database\Eloquent\Builder<static>|User query()
@@ -24,8 +24,6 @@ use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Cas
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_type * @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_type
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_docblock * @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_docblock
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_docblock_fqn * @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_docblock_fqn
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\MagicWhere\Model
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -9,8 +9,6 @@ use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Hooks\CustomMethod; use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Hooks\CustomMethod;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Hooks\CustomProperty; use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Hooks\CustomProperty;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Hooks\UnsetMethod; use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Hooks\UnsetMethod;
use Illuminate\Filesystem\Filesystem;
use Mockery;
class Test extends AbstractModelsCommand class Test extends AbstractModelsCommand
{ {
@@ -34,24 +32,6 @@ class Test extends AbstractModelsCommand
public function test(): void public function test(): void
{ {
$actualContent = null;
$mockFilesystem = Mockery::mock(Filesystem::class)->makePartial();
$mockFilesystem
->shouldReceive('get')
->andReturn(file_get_contents(__DIR__ . '/Models/Simple.php'))
->once();
$mockFilesystem
->shouldReceive('put')
->with(
Mockery::any(),
Mockery::capture($actualContent)
)
->andReturn(1) // Simulate we wrote _something_ to the file
->once();
$this->instance(Filesystem::class, $mockFilesystem);
$command = $this->app->make(ModelsCommand::class); $command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [ $tester = $this->runCommand($command, [
@@ -60,33 +40,6 @@ class Test extends AbstractModelsCommand
$this->assertSame(0, $tester->getStatusCode()); $this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay()); $this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
$expectedContent = <<<'PHP'
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Models;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @property int $id
* @property-read string $custom
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple custom($custom)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple whereId($value)
* @mixin \Eloquent
*/
class Simple extends Model
{
}
PHP;
$this->assertSame($expectedContent, $actualContent);
} }
} }
@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Models;
use Illuminate\Database\Eloquent\Model;
/**
* @property int $id
* @property-read string $custom
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple custom($custom)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple whereId($value)
* @mixin \Eloquent
*/
class Simple extends Model
{
}
@@ -8,8 +8,6 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo;
/** /**
*
*
* @property string $relation_morph_to_type * @property string $relation_morph_to_type
* @property int $relation_morph_to_id * @property int $relation_morph_to_id
* @property string|null $nullable_relation_morph_to_type * @property string|null $nullable_relation_morph_to_type
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\PHPStormNoInspec
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\PHPStormNoInspec
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
@@ -9,8 +9,6 @@ use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Pivot\Models\Pivots\Di
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property-read DifferentCustomPivot|CustomPivot|null $pivot * @property-read DifferentCustomPivot|CustomPivot|null $pivot
* @property-read \Illuminate\Database\Eloquent\Collection<int, ModelWithPivot> $relationCustomPivotUsingSameAccessor * @property-read \Illuminate\Database\Eloquent\Collection<int, ModelWithPivot> $relationCustomPivotUsingSameAccessor
* @property-read int|null $relation_custom_pivot_using_same_accessor_count * @property-read int|null $relation_custom_pivot_using_same_accessor_count
@@ -75,8 +73,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Pivot\Models\Piv
use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\Relations\Pivot;
/** /**
*
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomPivot newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|CustomPivot newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomPivot newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|CustomPivot newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomPivot query() * @method static \Illuminate\Database\Eloquent\Builder<static>|CustomPivot query()
@@ -94,8 +90,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Pivot\Models\Piv
use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\Relations\Pivot;
/** /**
*
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|DifferentCustomPivot newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|DifferentCustomPivot newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|DifferentCustomPivot newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|DifferentCustomPivot newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|DifferentCustomPivot query() * @method static \Illuminate\Database\Eloquent\Builder<static>|DifferentCustomPivot query()
@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\QueryScopes\Models;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* @comment Scope using the 'Scope' attribute
* @param Builder $query
* @return void
*/
#[Scope]
protected function local(Builder $query): void
{
$query->where('ip_address', '127.0.0.1');
}
/**
* @comment Scope using the 'scope' prefix
* @param Builder $query
* @return void
*/
protected function scopeSystem(Builder $query): void
{
$query->where('system', true);
}
}
@@ -4,9 +4,48 @@ declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\QueryScopes\Models; namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\QueryScopes\Models;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
* @method static Builder<static>|Comment local() Scope using the 'Scope' attribute
* @method static Builder<static>|Comment newModelQuery()
* @method static Builder<static>|Comment newQuery()
* @method static Builder<static>|Comment query()
* @method static Builder<static>|Comment system() Scope using the 'scope' prefix
* @mixin \Eloquent
*/
class Comment extends Model
{
/**
* @comment Scope using the 'Scope' attribute
* @param Builder $query
* @return void
*/
#[Scope]
protected function local(Builder $query): void
{
$query->where('ip_address', '127.0.0.1');
}
/**
* @comment Scope using the 'scope' prefix
* @param Builder $query
* @return void
*/
protected function scopeSystem(Builder $query): void
{
$query->where('system', true);
}
}
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\QueryScopes\Models;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -172,8 +211,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\QueryScopes\Mode
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|PostParent active() * @method static \Illuminate\Database\Eloquent\Builder<static>|PostParent active()
* @method static \Illuminate\Database\Eloquent\Builder<static>|PostParent newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|PostParent newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|PostParent newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|PostParent newQuery()
@@ -8,8 +8,6 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
/** /**
*
*
* @property int $id * @property int $id
* @property string|null $char_nullable * @property string|null $char_nullable
* @property string $char_not_nullable * @property string $char_not_nullable
@@ -8,8 +8,6 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** /**
*
*
* @property int $id * @property int $id
* @property int $not_null_column_with_foreign_key_constraint * @property int $not_null_column_with_foreign_key_constraint
* @property int $not_null_column_with_no_foreign_key_constraint * @property int $not_null_column_with_no_foreign_key_constraint
@@ -61,8 +59,6 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** /**
*
*
* @property int $id * @property int $id
* @property int $not_null_column_with_foreign_key_constraint * @property int $not_null_column_with_foreign_key_constraint
* @property int $not_null_column_with_no_foreign_key_constraint * @property int $not_null_column_with_no_foreign_key_constraint
@@ -132,8 +128,6 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\Relations\MorphToMany;
/** /**
*
*
* @property int $id * @property int $id
* @property-read Simple $relationBelongsTo * @property-read Simple $relationBelongsTo
* @property-read AnotherModel $relationBelongsToInAnotherNamespace * @property-read AnotherModel $relationBelongsToInAnotherNamespace
@@ -8,8 +8,6 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** /**
*
*
* @property int $id * @property int $id
* @property int $not_null_column_with_foreign_key_constraint * @property int $not_null_column_with_foreign_key_constraint
* @property int $not_null_column_with_no_foreign_key_constraint * @property int $not_null_column_with_no_foreign_key_constraint
@@ -61,8 +59,6 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
/** /**
*
*
* @property int $id * @property int $id
* @property int $not_null_column_with_foreign_key_constraint * @property int $not_null_column_with_foreign_key_constraint
* @property int $not_null_column_with_no_foreign_key_constraint * @property int $not_null_column_with_no_foreign_key_constraint
@@ -132,8 +128,6 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\Relations\MorphToMany;
/** /**
*
*
* @property int $id * @property int $id
* @property-read Simple|null $relationBelongsTo * @property-read Simple|null $relationBelongsTo
* @property-read AnotherModel|null $relationBelongsToInAnotherNamespace * @property-read AnotherModel|null $relationBelongsToInAnotherNamespace
@@ -7,8 +7,6 @@ namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\SimpleCasts\Mode
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $cast_to_int * @property int $cast_to_int
* @property int $cast_to_integer * @property int $cast_to_integer
* @property float $cast_to_real * @property float $cast_to_real
@@ -33,7 +31,7 @@ use Illuminate\Database\Eloquent\Model;
* @property \Carbon\CarbonImmutable $cast_to_immutable_datetime * @property \Carbon\CarbonImmutable $cast_to_immutable_datetime
* @property \Carbon\CarbonImmutable $cast_to_immutable_datetime_serialization * @property \Carbon\CarbonImmutable $cast_to_immutable_datetime_serialization
* @property int $cast_to_timestamp * @property int $cast_to_timestamp
* @property mixed $cast_to_encrypted * @property string $cast_to_encrypted
* @property array<array-key, mixed> $cast_to_encrypted_array * @property array<array-key, mixed> $cast_to_encrypted_array
* @property \Illuminate\Support\Collection<array-key, mixed> $cast_to_encrypted_collection * @property \Illuminate\Support\Collection<array-key, mixed> $cast_to_encrypted_collection
* @property array<array-key, mixed> $cast_to_encrypted_json * @property array<array-key, mixed> $cast_to_encrypted_json
@@ -8,15 +8,13 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
*
*
* @property int $id * @property int $id
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple onlyTrashed() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple query() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple whereId($value) * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple withTrashed() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple withTrashed(bool $withTrashed = true)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple withoutTrashed() * @method static \Illuminate\Database\Eloquent\Builder<static>|Simple withoutTrashed()
* @mixin \Eloquent * @mixin \Eloquent
*/ */
@@ -9,8 +9,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Query\Builder; use Illuminate\Database\Query\Builder;
/** /**
*
*
* @property-read string|int|null $foo * @property-read string|int|null $foo
* @property-read \Illuminate\Database\Eloquent\Collection<int, UnionTypeModel> $withUnionTypeReturn * @property-read \Illuminate\Database\Eloquent\Collection<int, UnionTypeModel> $withUnionTypeReturn
* @property-read int|null $with_union_type_return_count * @property-read int|null $with_union_type_return_count
@@ -8,8 +8,6 @@ use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
*
*
* @property int $id * @property int $id
* @method static Builder<static>|Simple newModelQuery() * @method static Builder<static>|Simple newModelQuery()
* @method static Builder<static>|Simple newQuery() * @method static Builder<static>|Simple newQuery()
@@ -1,6 +1,4 @@
/** /**
*
*
* @mixin \Eloquent * @mixin \Eloquent
* @mixin \Illuminate\Database\Eloquent\Builder * @mixin \Illuminate\Database\Eloquent\Builder
* @mixin \Illuminate\Database\Query\Builder * @mixin \Illuminate\Database\Query\Builder
+2 -4
View File
@@ -242,13 +242,11 @@ class MacroTest extends TestCase
$macro = new Macro($reflectionMethod, 'URL', new ReflectionClass(UrlGenerator::class), 'macroName'); $macro = new Macro($reflectionMethod, 'URL', new ReflectionClass(UrlGenerator::class), 'macroName');
$output = <<<'DOC' $output = <<<'DOC'
/** /**
*
*
* @param string $foo * @param string $foo
* @param int $bar * @param int $bar
* @return string * @return string
* @see \Barryvdh\LaravelIdeHelper\Tests\UrlGeneratorMacroClass::__invoke() * @see \Barryvdh\LaravelIdeHelper\Tests\UrlGeneratorMacroClass::__invoke()
* @static * @static
*/ */
DOC; DOC;
$this->assertSame($output, $macro->getDocComment('')); $this->assertSame($output, $macro->getDocComment(''));
+32 -13
View File
@@ -36,12 +36,10 @@ class MethodTest extends TestCase
$output = <<<'DOC' $output = <<<'DOC'
/** /**
*
*
* @param string $last * @param string $last
* @param string $first * @param string $first
* @param string $middle * @param string $middle
* @static * @static
*/ */
DOC; DOC;
$this->assertSame($output, $method->getDocComment('')); $this->assertSame($output, $method->getDocComment(''));
@@ -71,8 +69,8 @@ DOC;
* @param array $values * @param array $values
* @param array|string $uniqueBy * @param array|string $uniqueBy
* @param array|null $update * @param array|null $update
* @return int * @return int
* @static * @static
*/ */
DOC; DOC;
$this->assertSame($output, $method->getDocComment('')); $this->assertSame($output, $method->getDocComment(''));
@@ -104,8 +102,8 @@ DOC;
* @param mixed $operator * @param mixed $operator
* @param mixed $value * @param mixed $value
* @param string $boolean * @param string $boolean
* @return \Illuminate\Database\Eloquent\Builder<static> * @return \Illuminate\Database\Eloquent\Builder<static>
* @static * @static
*/ */
DOC; DOC;
$this->assertSame($output, $method->getDocComment('')); $this->assertSame($output, $method->getDocComment(''));
@@ -134,8 +132,8 @@ DOC;
* @param string|array|\Illuminate\Contracts\Database\Query\Expression $columns * @param string|array|\Illuminate\Contracts\Database\Query\Expression $columns
* @param string $boolean * @param string $boolean
* @param bool $not * @param bool $not
* @return \Illuminate\Database\Eloquent\Builder<static> * @return \Illuminate\Database\Eloquent\Builder<static>
* @static * @static
*/ */
DOC; DOC;
@@ -177,10 +175,8 @@ DOC;
$output = <<<'DOC' $output = <<<'DOC'
/** /**
* * @return \Illuminate\Foundation\Application
* * @static
* @return \Illuminate\Foundation\Application
* @static
*/ */
DOC; DOC;
@@ -193,6 +189,29 @@ DOC;
$this->assertSame([], $method->getParamsWithDefault(false)); $this->assertSame([], $method->getParamsWithDefault(false));
$this->assertTrue($method->shouldReturn()); $this->assertTrue($method->shouldReturn());
} }
public function testEloquentBuilderWithTemplates()
{
$reflectionClass = new \ReflectionClass(EloquentBuilder::class);
$reflectionMethod = $reflectionClass->getMethod('firstOr');
$method = new Method($reflectionMethod, 'Builder', $reflectionClass, null, [], [], [], ['TModel']);
$output = <<<'DOC'
/**
* Execute the query and get the first result or call a callback.
*
* @template TValue
* @param (\Closure(): TValue)|list<string> $columns
* @param (\Closure(): TValue)|null $callback
* @return TModel|TValue
* @static
*/
DOC;
$this->assertSame($output, $method->getDocComment(''));
$this->assertSame('firstOr', $method->getName());
$this->assertSame('\\' . EloquentBuilder::class, $method->getDeclaringClass());
}
} }
class ExampleClass class ExampleClass
+2 -2
View File
@@ -11,7 +11,7 @@ class SnapshotPhpDriver implements Driver
{ {
public function serialize($data): string public function serialize($data): string
{ {
return (string) $data; return str_replace(["\r\n", "\r"], "\n", (string) $data);
} }
public function extension(): string public function extension(): string
@@ -21,6 +21,6 @@ class SnapshotPhpDriver implements Driver
public function match($expected, $actual) public function match($expected, $actual)
{ {
Assert::assertSame($expected, $this->serialize($actual)); Assert::assertSame(str_replace(["\r\n", "\r"], "\n", $expected), $this->serialize($actual));
} }
} }
+2 -2
View File
@@ -11,7 +11,7 @@ class SnapshotTxtDriver implements Driver
{ {
public function serialize($data): string public function serialize($data): string
{ {
return (string) $data; return str_replace(["\r\n", "\r"], "\n", (string) $data);
} }
public function extension(): string public function extension(): string
@@ -21,6 +21,6 @@ class SnapshotTxtDriver implements Driver
public function match($expected, $actual) public function match($expected, $actual)
{ {
Assert::assertSame($expected, $this->serialize($actual)); Assert::assertSame(str_replace(["\r\n", "\r"], "\n", $expected), $this->serialize($actual));
} }
} }
+6
View File
@@ -55,6 +55,11 @@ abstract class TestCase extends BaseTestCase
$this->assertMatchesSnapshot($actualContent, new SnapshotTxtDriver()); $this->assertMatchesSnapshot($actualContent, new SnapshotTxtDriver());
} }
protected function assertMatchesMockedSnapshot()
{
$this->assertMatchesSnapshot($this->mockFilesystemOutput, new SnapshotPhpDriver());
}
protected function mockFilesystem() protected function mockFilesystem()
{ {
$mockFilesystem = Mockery::mock(Filesystem::class)->makePartial(); $mockFilesystem = Mockery::mock(Filesystem::class)->makePartial();
@@ -66,6 +71,7 @@ abstract class TestCase extends BaseTestCase
Mockery::any() Mockery::any()
) )
->andReturnUsing(function ($path, $contents) { ->andReturnUsing(function ($path, $contents) {
$contents = str_replace(["\r\n", "\r"], "\n", $contents);
$this->mockFilesystemOutput .= $contents; $this->mockFilesystemOutput .= $contents;
return strlen($contents); return strlen($contents);
-56
View File
@@ -1,56 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests;
use Barryvdh\LaravelIdeHelper\UsesResolver;
use PHPUnit\Framework\TestCase;
class UsesResolverTest extends TestCase
{
/**
* Test that we can correctly load uses from supplied code
*/
public function testLoadFromCode()
{
$usesResolver = new UsesResolver();
$code = <<<'DOC'
<?php
namespace Barryvdh\LaravelIdeHelper\Tests;
use Barryvdh\LaravelIdeHelper\UsesResolver as MyUsesResolver;
use PHPUnit\Framework\TestCase;
class UsesResolverTest extends TestCase
{
//
}
DOC;
$this->assertEquals(
$usesResolver->loadFromCode('Barryvdh\\LaravelIdeHelper\\Tests\\UsesResolverTest', $code),
[
'MyUsesResolver' => '\\Barryvdh\\LaravelIdeHelper\\UsesResolver',
'TestCase' => '\\PHPUnit\Framework\TestCase',
]
);
}
/**
* Test that we can correctly load uses from a class
*/
public function testLoadFromClass()
{
$usesResolver = new UsesResolver();
$this->assertEquals(
$usesResolver->loadFromClass(self::class),
[
'UsesResolver' => '\\Barryvdh\\LaravelIdeHelper\\UsesResolver',
'TestCase' => '\\PHPUnit\Framework\TestCase',
]
);
}
}