PHPDoc return type for trait function - php-7

I have functions like the following in my code that return the object (for chaining):
/**
* Set properties
*
* #param $name
* #param $value
*
* #return \Boka10\Page\MenuItemConfig
*/
public function __set($name, $value)
{
$this->$name = $value;
return $this;
}
I want to move this function into a trait because, well, basically it is reused all the time.
My problem is, that the return $this line makes problems in the documentation section. In my PHPDoc it says (in this example) #return \Boka10\Page\MenuItemConfig.
How do I create a "global" trait method whose return documentation contains the correct typecast? Is it possible to do that or should I just add the __set function to each class?
I am not sure if I can explain what problem I am having here ;) What exactly would be the content of the #return tag in a globally used trait if all of these objects return their own instance?

After some digging and "hacking" I checked out the tests in Psalm and found, that the following seems to be the best method to comment these cases:
/**
* #method string somefunction($name, $value)
* #property string $name
*/
class ImplementTrait {
use MagicTrait;
}
The properties and methods are documented on the implementing class.
Note: I am using Psalm to check the code quality and this is psalms accepted way:
Psalm Tests for __call annotations
Psalm tests for __get/__set annotations

I use the following approach to add auto-completion in PHPStorm when using classes that implement some interfaces.
I create an interface with a skeleton of all target Trait public methods and extend it.
Example:
Trait MySimpleTrait {
/**
* #inheritDoc
*/
public function someMethod($someArg){
return doSomethingWithSomeArg($someArg);
}
}
Interface MySimpleTraitInterface {
/**
*
* This method do some thing with <var>$someArg</>
*
* #param mixed $someArg
* #return mixed
*/
public function someMethod($someArg);
}
interface MySimpleServiceInterface extends MySimpleTraitInterface
{
}
class MySimpleService implements MySimpleServiceInterface
{
use MySimpleTrait;
}
PHPStorm showing autocomplete for method defined in Trait:
PHPStorm showing phpDoc for method defined in Trait:
Seems absurd in 2022, but I have a lot of projects with PHP 5.6 and the syntax is supposed to be compatible (i.e., no typehint in non-scalar args or return functions).

Related

Need to check sub class (of Class type) if it inherits from super class, using custom Detector via method visitCallExpression(UCallExpression)

I have created my own lint Detector.visitCallExpression(UCallExpression) and I need to find a way to check if a MyClass class parameter passed into a method call is a child of MyParent class?
//Example having this below code somewhere to be Lint scanned.
someObject.method(MyClass.class)
How can I determine MyClass.class inherits from MyParent class?
//Using the IntelliJ InheritanceUtil utility class
//Converts argument of MyClass.class -> psiClass
InheritanceUtil.isInheritor(psiClass, "com.somePackage.MyParent")
The PsiClass I get from the MyClass.class parameter, is resolved to the base java.lang.Class object, so the InheritanceUtil check always return false~
Anyway i found the solution
/**
* Detects if a Class<?> => PsiClass:Class<?> is a subclass of a PsiClass(?)
*
* #param type The PsiType object that is a PsiClass of the class to be checked for subclass
* #param compareToParentCanonicalClass The Class canonical name to be compared as a super/parent class
*
* #return true if the PsiType is a subclass of compareToParentCanonicalClass, false otherwise
*/
open fun isPsiTypeSubClassOfParentClassType(type: PsiType, compareToParentCanonicalClass: String): Boolean {
println("superClass checking:$type")
var psiClss = PsiTypesUtil.getPsiClass(type)
val pct = type as PsiClassType
val psiTypes: List<PsiType> = ArrayList<PsiType>(pct.resolveGenerics().substitutor.substitutionMap.values)
for (i in psiTypes.indices) {
println("canonical:"+ psiTypes[i].canonicalText)
var psiClass = psiClss?.let { JavaPsiFacade.getInstance(it.project).findClass(psiTypes[i].canonicalText, psiClss.resolveScope) }
return InheritanceUtil.isInheritor(psiClass, compareToParentCanonicalClass)
}
return false;
}

JSDOC datatype in #param

In jsdoc #param,
We can write like:
/**
* #param {Object} somebody- The employee who is responsible.
*/
function sayHello(somebody: ABC) {
alert('Hello ' + somebody);
}
If I have a class like ABC and somebody is an object of type ABC, can I write it like this,?
/**
* #param {ABC} somebody- The employee who is responsible.
*/
function sayHello(somebody: ABC) {
alert('Hello ' + somebody);
}
That is, can I give my own object type inside curly braces of param rather than giving as object? Thanks in advance...
Looking at your code you are probably using TypeScript. You have 2 options:
If ABC is an object or class you can reference it by using a JSDoc namepath (ex: myNamespaceOrModule.ABC};
If ABC is not an actual JavaScript object (ex: a TypeScript interface) than you can use JSDoc #typedef tag to document a custom tag.
Please, provide the code where the ABC class is defined for a better answer.

Custom onNext() implementation for RxJava and Retrofit

I'm using RxJava alongside Retrofit and I'm trying to find a really clean way of abstracting my API calls in such a way that I can minimize code in the Activity.
So far, I have something like this:
Observable<SomeObservable> combined =
Observable.zip(firstObservable, secondObservable, SomeObservable::new);
// Works but needs header parsing
RxRestNetworker.performAsyncApiCall(combined, (returnData) -> {
// onNext() implementation
}, () -> hideSuggestionProgress());
The RxRestNetworker class looks like:
public class RxRestNetworker {
private static final String LOG_TAG = RxRestNetworker.class.getCanonicalName();
// Default error handling
private static Action1<Throwable> mOnError = throwable -> {
Log.e(LOG_TAG, throwable.getMessage());
throwable.printStackTrace();
};
/**
* Perform the desired request with default error handling
* #param observable
* #param onAction
* #param <T>
* #return
*/
public static <T> Subscription performAsyncApiCall(Observable<T> observable, Action1<? super T> onAction, Action0 onComplete) {
// Use default error handling
return performAsyncApiCall(observable, onAction, mOnError, onComplete);
}
/**
* Perform the desired request with some error handling OTHER than the default one
* #param observable
* #param onAction
* #param onError
* #param <T>
* #return
*/
public static <T> Subscription performAsyncApiCall(Observable<T> observable, Action1<? super T> onAction, Action1<Throwable> onError, Action0 onComplete) {
return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(onAction, onError, onComplete);
}
}
So you can see I'm using the default onError() by calling the first performAsyncApiCall method.
Now this all works, but I need to access the headers of the response by getting access to the response object.
This post claimed that I should wrap my response object and declare it like so in the API:
Observable<Response<SomeResponse>> getThings();
But I don't really care for that. It seems ugly and makes zipping observables like above a headache.
Ideally, I'd like to create an abstraction of the onNext() Action1 argument that can by default log the headers and do anything else done for every API call, then pass the results of the call back to the caller. Am I going in the wrong direction with this? Can somebody please help me find a way to abstract this in a very clean manner?
Thank you!

PHP Static and Normal Functions Calling [duplicate]

There are two distinct ways to access methods in PHP, but what's the difference?
$response->setParameter('foo', 'bar');
and
sfConfig::set('foo', 'bar');
I'm assuming -> (dash with greater than sign or chevron) is used for functions for variables, and :: (double colons) is used for functions for classes. Correct?
Is the => assignment operator only used to assign data within an array? Is this in contrast to the = assignment operator which is used to instantiate or modify a variable?
When the left part is an object instance, you use ->. Otherwise, you use ::.
This means that -> is mostly used to access instance members (though it can also be used to access static members, such usage is discouraged), while :: is usually used to access static members (though in a few special cases, it's used to access instance members).
In general, :: is used for scope resolution, and it may have either a class name, parent, self, or (in PHP 5.3) static to its left. parent refers to the scope of the superclass of the class where it's used; self refers to the scope of the class where it's used; static refers to the "called scope" (see late static bindings).
The rule is that a call with :: is an instance call if and only if:
the target method is not declared as static and
there is a compatible object context at the time of the call, meaning these must be true:
the call is made from a context where $this exists and
the class of $this is either the class of the method being called or a subclass of it.
Example:
class A {
public function func_instance() {
echo "in ", __METHOD__, "\n";
}
public function callDynamic() {
echo "in ", __METHOD__, "\n";
B::dyn();
}
}
class B extends A {
public static $prop_static = 'B::$prop_static value';
public $prop_instance = 'B::$prop_instance value';
public function func_instance() {
echo "in ", __METHOD__, "\n";
/* this is one exception where :: is required to access an
* instance member.
* The super implementation of func_instance is being
* accessed here */
parent::func_instance();
A::func_instance(); //same as the statement above
}
public static function func_static() {
echo "in ", __METHOD__, "\n";
}
public function __call($name, $arguments) {
echo "in dynamic $name (__call)", "\n";
}
public static function __callStatic($name, $arguments) {
echo "in dynamic $name (__callStatic)", "\n";
}
}
echo 'B::$prop_static: ', B::$prop_static, "\n";
echo 'B::func_static(): ', B::func_static(), "\n";
$a = new A;
$b = new B;
echo '$b->prop_instance: ', $b->prop_instance, "\n";
//not recommended (static method called as instance method):
echo '$b->func_static(): ', $b->func_static(), "\n";
echo '$b->func_instance():', "\n", $b->func_instance(), "\n";
/* This is more tricky
* in the first case, a static call is made because $this is an
* instance of A, so B::dyn() is a method of an incompatible class
*/
echo '$a->dyn():', "\n", $a->callDynamic(), "\n";
/* in this case, an instance call is made because $this is an
* instance of B (despite the fact we are in a method of A), so
* B::dyn() is a method of a compatible class (namely, it's the
* same class as the object's)
*/
echo '$b->dyn():', "\n", $b->callDynamic(), "\n";
Output:
B::$prop_static: B::$prop_static value
B::func_static(): in B::func_static
$b->prop_instance: B::$prop_instance value
$b->func_static(): in B::func_static
$b->func_instance():
in B::func_instance
in A::func_instance
in A::func_instance
$a->dyn():
in A::callDynamic
in dynamic dyn (__callStatic)
$b->dyn():
in A::callDynamic
in dynamic dyn (__call)
:: is used in static context, ie. when some method or property is declared as static:
class Math {
public static function sin($angle) {
return ...;
}
}
$result = Math::sin(123);
Also, the :: operator (the Scope Resolution Operator, a.k.a Paamayim Nekudotayim) is used in dynamic context when you invoke a method/property of a parent class:
class Rectangle {
protected $x, $y;
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
}
class Square extends Rectangle {
public function __construct($x) {
parent::__construct($x, $x);
}
}
-> is used in dynamic context, ie. when you deal with some instance of some class:
class Hello {
public function say() {
echo 'hello!';
}
}
$h = new Hello();
$h->say();
By the way: I don't think that using Symfony is a good idea when you don't have any OOP experience.
Actually by this symbol we can call a class method that is static and not be dependent on other initialization...
class Test {
public $name;
public function __construct() {
$this->name = 'Mrinmoy Ghoshal';
}
public static function doWrite($name) {
print 'Hello '.$name;
}
public function write() {
print $this->name;
}
}
Here the doWrite() function is not dependent on any other method or variable, and it is a static method. That's why we can call this method by this operator without initializing the object of this class.
Test::doWrite('Mrinmoy');
// Output: Hello Mrinmoy.
But if you want to call the write method in this way, it will generate an error because it is dependent on initialization.
The => operator is used to assign key-value pairs in an associative array. For example:
$fruits = array(
'Apple' => 'Red',
'Banana' => 'Yellow'
);
It's meaning is similar in the foreach statement:
foreach ($fruits as $fruit => $color)
echo "$fruit is $color in color.";
The difference between static and instantiated methods and properties seem to be one of the biggest obstacles to those just starting out with OOP PHP in PHP 5.
The double colon operator (which is called the Paamayim Nekudotayim from Hebrew - trivia) is used when calling an object or property from a static context. This means an instance of the object has not been created yet.
The arrow operator, conversely, calls methods or properties that from a reference of an instance of the object.
Static methods can be especially useful in object models that are linked to a database for create and delete methods, since you can set the return value to the inserted table id and then use the constructor to instantiate the object by the row id.
Yes, I just hit my first 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. My bad, I had a $instance::method() that should have been $instance->method(). Silly me.
The odd thing is that this still works just fine on my local machine (running PHP 5.3.8) - nothing, not even a warning with error_reporting = E_ALL - but not at all on the test server, there it just explodes with a syntax error and a white screen in the browser. Since PHP logging was turned off at the test machine, and the hosting company was too busy to turn it on, it was not too obvious.
So, word of warning: apparently, some PHP installations will let you use a $instance::method(), while others don't.
If anybody can expand on why that is, please do.

Closure Compiler - can a method be public ONLY for testing?

I have a method that I need to test, but ultimately I don't want this method to be public. Is there a tag I can use so that I can use the method in my tests (as if it were public) but the method will be private in the final result?
One way to do this would be to define a compiler #define value, that you set either for test code or unset otherwise:
/** #define {boolean} */
var TESTING = false;
then you can do something like this:
if (TESTING) {
var someMethodVisibleForTesting = function() {}
}
This is about your only option.