Commit 365436f4 authored by Andreas Fernandez's avatar Andreas Fernandez
Browse files

[TASK] Add support for class-string annotation and provide meta file

PhpStorm has basic support for generics since version 2021.2 which comes
in handy as since the same version the "Dynamic Return Type" plugin is broken.

Providing the class-string annotation and a proper return generic
supersedes this and recovers the built-in autocompletion.

To have the same effect for both, 3rd party code not being under our
control or methods having complex returns based on their input, a
`.phpstorm.meta.php` file is provided extending PhpStorms code awareness
capabilities.
Tons of kudos to Alexander Schnitzler providing a boilerplate
configuration here:
https://github.com/alexanderschnitzler/phpstorm.meta.php-typo3

For more information about capability extension consult
https://www.jetbrains.com/help/phpstorm/ide-advanced-metadata.html

Resolves: #95064
Releases: master, 10.4, 9.5
Change-Id: I4ea5115550ce7070de01c42c19ac3b93bf6ab4b6
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70895


Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent 7cb81a31
<?php
/**
* Extend PhpStorms code completion capabilities by providing a meta file
*
* Kudos to Alexander Schnitzler's work, see https://github.com/alexanderschnitzler/phpstorm.meta.php-typo3
* @link https://www.jetbrains.com/help/phpstorm/ide-advanced-metadata.html
*/
namespace PHPSTORM_META {
// Tests
override(\TYPO3\TestingFramework\Core\BaseTestCase::getAccessibleMock(0), type(0));
override(\TYPO3\TestingFramework\Core\BaseTestCase::getAccessibleMockForAbstractClass(0), type(0));
// Contexts
// @see https://docs.typo3.org/c/typo3/cms-core/master/en-us/Changelog/9.4/Feature-85389-ContextAPIForConsistentDataHandling.html
expectedArguments(
\TYPO3\CMS\Core\Context\Context::getAspect(),
0,
'date',
'visibility',
'backend.user',
'frontend.user',
'workspace',
'language',
'typoscript'
);
override(\TYPO3\CMS\Core\Context\Context::getAspect(), map([
'date' => \TYPO3\CMS\Core\Context\DateTimeAspect::class,
'visibility' => \TYPO3\CMS\Core\Context\VisibilityAspect::class,
'backend.user' => \TYPO3\CMS\Core\Context\UserAspect::class,
'frontend.user' => \TYPO3\CMS\Core\Context\UserAspect::class,
'workspace' => \TYPO3\CMS\Core\Context\WorkspaceAspect::class,
'language' => \TYPO3\CMS\Core\Context\LanguageAspect::class,
'typoscript' => \TYPO3\CMS\Core\Context\TypoScriptAspect::class,
]));
expectedArguments(
\TYPO3\CMS\Core\Context\DateTimeAspect::get(),
0,
'timestamp',
'iso',
'timezone',
'full',
'accessTime'
);
expectedArguments(
\TYPO3\CMS\Core\Context\VisibilityAspect::get(),
0,
'includeHiddenPages',
'includeHiddenContent',
'includeDeletedRecords'
);
expectedArguments(
\TYPO3\CMS\Core\Context\UserAspect::get(),
0,
'id',
'username',
'isLoggedIn',
'isAdmin',
'groupIds',
'groupNames'
);
expectedArguments(
\TYPO3\CMS\Core\Context\WorkspaceAspect::get(),
0,
'id',
'isLive',
'isOffline'
);
expectedArguments(
\TYPO3\CMS\Core\Context\LanguageAspect::get(),
0,
'id',
'contentId',
'fallbackChain',
'overlayType',
'legacyLanguageMode',
'legacyOverlayType'
);
expectedArguments(
\TYPO3\CMS\Core\Context\TypoScriptAspect::get(),
0,
'forcedTemplateParsing'
);
}
......@@ -73,7 +73,9 @@ class NodeVisitor extends NodeVisitorAbstract
'Transient', 'Extbase\\\\ORM\\\\Lazy', 'Enum',
'TYPO3\\\\CMS\\\\Extbase\\\\Annotation\\\\ORM\\\\Cascade', 'Extbase\\\\ORM\\\\Cascade', 'Cascade',
// Extension scanner
'extensionScannerIgnoreFile', 'extensionScannerIgnoreLine'
'extensionScannerIgnoreFile', 'extensionScannerIgnoreLine',
// static code analysis
'template', 'implements', 'extends'
];
$matches = [];
......
{
// configuration file for PHPStorm Plugin: http://plugins.jetbrains.com/plugin/7251
"methodCalls": [
{
"class": "\\TYPO3\\CMS\\Core\\Utility\\GeneralUtility",
"method": "makeInstance",
"position": 0
},
{
"class": "\\TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface",
"method": "get",
"position": 0
},
{
"class": "\\PHPUnit\\Framework\\TestCase",
"method": "prophesize",
"position": 0,
"mask": "%s|\\Prophecy\\Prophecy\\ObjectProphecy"
},
{
"class": "\\PHPUnit\\Framework\\TestCase",
"method": "createMock",
"position": 0,
"mask": "%s|\\PHPUnit_Framework_MockObject_MockObject"
},
{
"class": "\\TYPO3\\TestingFramework\\Core\\BaseTestCase",
"method": "getAccessibleMock",
"position": 0,
"mask": "%s|\\PHPUnit_Framework_MockObject_MockObject|\\TYPO3\\TestingFramework\\Core\\AccessibleObjectInterface"
},
{
"class": "\\TYPO3\\TestingFramework\\Core\\BaseTestCase",
"method": "getAccessibleMockForAbstractClass",
"position": 0,
"mask": "%s|\\PHPUnit_Framework_MockObject_MockObject|\\TYPO3\\TestingFramework\\Core\\AccessibleObjectInterface"
}
],
"functionCalls": [
]
}
......@@ -3653,9 +3653,10 @@ class GeneralUtility
* GeneralUtility::makeInstance() first and call its get() method to get
* the instance of a specific class.
*
* @param string $className name of the class to instantiate, must not be empty and not start with a backslash
* @template T
* @param string|class-string<T> $className name of the class to instantiate, must not be empty and not start with a backslash
* @param array<int, mixed> $constructorArguments Arguments for the constructor
* @return object the created instance
* @return object&T the created instance
* @throws \InvalidArgumentException if $className is empty or starts with a backslash
*/
public static function makeInstance($className, ...$constructorArguments)
......
......@@ -24,6 +24,7 @@ use TYPO3\CMS\Extbase\Reflection\ReflectionService;
/**
* Internal TYPO3 Dependency Injection container
* @internal only to be used within Extbase, not part of TYPO3 Core API.
* @template T
*/
class Container implements \TYPO3\CMS\Core\SingletonInterface
{
......@@ -79,9 +80,9 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface
* Main method which should be used to get an instance of the wished class
* specified by $className.
*
* @param string $className
* @param string|class-string<T> $className
* @param array $givenConstructorArguments the list of constructor arguments as array
* @return object the built object
* @return object&T the built object
* @internal
*/
public function getInstance($className, $givenConstructorArguments = [])
......@@ -93,8 +94,8 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface
/**
* Create an instance of $className without calling its constructor
*
* @param string $className
* @return object
* @param string|class-string<T> $className
* @return object&T
*/
public function getEmptyObject($className)
{
......@@ -109,11 +110,11 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface
/**
* Internal implementation for getting a class.
*
* @param string $className
* @param string|class-string<T> $className
* @param array $givenConstructorArguments the list of constructor arguments as array
* @throws \TYPO3\CMS\Extbase\Object\Exception
* @throws \TYPO3\CMS\Extbase\Object\Exception\CannotBuildObjectException
* @return object the built object
* @return object&T the built object
*/
protected function getInstanceInternal($className, ...$givenConstructorArguments)
{
......
......@@ -18,6 +18,8 @@ use TYPO3\CMS\Extbase\Object\Container\Container;
/**
* Implementation of the default Extbase Object Manager
*
* @template T
*/
class ObjectManager implements ObjectManagerInterface
{
......@@ -86,9 +88,9 @@ class ObjectManager implements ObjectManagerInterface
/**
* Returns a fresh or existing instance of the object specified by $objectName.
*
* @param string $objectName The name of the object to return an instance of
* @param string|class-string<T> $objectName The name of the object to return an instance of
* @param array $constructorArguments
* @return object The object instance
* @return object&T The object instance
*/
public function get($objectName, ...$constructorArguments)
{
......@@ -118,8 +120,8 @@ class ObjectManager implements ObjectManagerInterface
/**
* Create an instance of $className without calling its constructor
*
* @param string $className
* @return object
* @param string|class-string<T> $className
* @return object&T
*/
public function getEmptyObject($className)
{
......
......@@ -16,6 +16,8 @@ namespace TYPO3\CMS\Extbase\Object;
/**
* Interface for the TYPO3 Object Manager
*
* @template T
*/
interface ObjectManagerInterface extends \TYPO3\CMS\Core\SingletonInterface
{
......@@ -31,17 +33,17 @@ interface ObjectManagerInterface extends \TYPO3\CMS\Core\SingletonInterface
/**
* Returns a fresh or existing instance of the object specified by $objectName.
*
* @param string $objectName The name of the object to return an instance of
* @param string|class-string<T> $objectName The name of the object to return an instance of
* @param array ...$constructorArguments
* @return object The object instance
* @return object&T The object instance
*/
public function get($objectName, ...$constructorArguments);
/**
* Create an instance of $className without calling its constructor
*
* @param string $className
* @return object
* @param string|class-string<T> $className
* @return object&T
*/
public function getEmptyObject($className);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment