PhpStorm to support registry pattern - phpstorm

In my code I use Registry pattern like that:
$data = Registry::get('classA')->methodOfClassA($param1, param2);
Registry class stores instances of some classes in internal array, so in any place of my code I can call class methods for handy functions like in line above.
But, the problem is that PHP-storm does not autocomplete when I type:
Registry::get('classA')->
And, that is worse, it does not go to declaration of the method "methodOfClassA" when I hover mouse cursor holding mac-button (analogue of control-button on windows)
I suppose, that IDE AI is not so good to recognise cases like that, but maybe there is some tricks to do that in a hard way? hardcoding classes+method names in some file and so on...
At least, I want it to understand to go to method declaration when I click method name...
Any advices?

http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata
This link describes it all -- it is already used by multiple projects/frameworks/code-generation helpers, like Magento, for example (some other can be found mentioned in the comments of the actual ticket).
For other situations you may want to check out DynamicReturnTypePlugin plugin (Settings | Plugins | Browse repositories...) -- have not tried myself and therefore cannot comment how good/fast/laggy it is.

You can always indicate the variable type in two steps:
/** #var $foo MyClass */
$foo = $this->get('MyClass');
$foo->bar(); // autocomplete works

Related

Can I tell PhpStorm what the return type of a function is going to be?

So if I have a function and in the PHPDoc I specify it'll return a SqsProcessResult object, then I call a function to create a new one of those objects but that function's PHPDoc say return type of Object (as it's a generic factory function) PhpStorm throws up an orange warning.
Can I annotate or otherwise tell PhpStorm the return type will be SqsProcessResult?
Yes, you can .. but due to the nature of the issue it may not be cleanest/elegant solution (at least that's what others may say).
Few options:
#1. Just suppress this inspection for that line.
Place caret in the highlighted area and press Alt + Enter (or get the same menu via "light bulb" icon)
Find the most suitable entry .. and press Arrow Right key (or mouse click on the tiny triangle icon) to expand submenu
Once there -- choose Suppress for statement option -- a new inline PHPDoc comment will be added just above tat line that instructs PhpStorm to ignore that specific Inspection in the next line.
Will be something like this:
/** #noinspection PhpIncompatibleReturnTypeInspection */
return \Yii::createObject(...);
Pros: no warning from IDE side
Cons: extra PHPDoc comment to satisfy IDE (which is needed considering the circumstances)
#2. Use some intermediate variable that you can type hint in place.
Add something like this instead of that existing single line:
/** #var SqsProcessResult $res */
$res = \Yii::createObject(...);
return $res;
Pros: no suppression comment
Cons: extra variable (and still extra PHPDoc comment) for basically no reason
This one mainly can be used in longer methods where such variable (generic Object) will be created in the beginning/middle of the function body and then used later.
#3. Play with .metadata functionality and provide resolution logic for actual \Yii::createObject() (so IDE chooses the right class based on input parameter).
https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata
This is how quite a few tools working: IDE helper for Laravel, Symfony helpers, DI Container helpers etc

Why does a function name have to be specified in a use statement?

In perl, sometimes it is necessary to specify the function name in the use statement.
For example:
use Data::DPath ('dpath');
will work but
use Data::DPath;
won't.
Other modules don't need the function names specified, for example:
use WWW::Mechanize;
Why?
Each module chooses what functions it exports by default. Some choose to export no functions by default at all, you have to ask for them. There's a few good reasons to do this, and one bad one.
If you're a class like WWW::Mechanize, then you don't need to export any functions. Everything is a class or object method. my $mech = WWW::Mechanize->new.
If you're a pragma like strict then there are no functions nor methods, it does its work simply by being loaded.
Some modules export waaay too many functions by default. An example is Test::Deep which exports...
all any array array_each arrayelementsonly arraylength arraylengthonly bag blessed bool cmp_bag cmp_deeply cmp_methods cmp_set code eq_deeply hash
hash_each hashkeys hashkeysonly ignore Isa isa listmethods methods noclass
none noneof num obj_isa re reftype regexpmatches regexponly regexpref
regexprefonly scalarrefonly scalref set shallow str subbagof subhashof
subsetof superbagof superhashof supersetof useclass
The problem comes when another module tries to export the same functions, or if you write a function with the same name. Then they clash and you get mysterious warnings.
$ cat ~/tmp/test.plx
use Test::Deep;
use List::Util qw(all);
$ perl -w ~/tmp/test.plx
Subroutine main::all redefined at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66.
at /Users/schwern/tmp/test.plx line 2.
Prototype mismatch: sub main::all: none vs (&#) at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66.
at /Users/schwern/tmp/test.plx line 2.
For this reason, exporting lots of functions is discouraged. For example, the Exporter documentation advises...
Do not export method names!
Do not export anything else by default without a good reason!
Exports pollute the namespace of the module user. If you must export try to use #EXPORT_OK in preference to #EXPORT and avoid short or common symbol names to reduce the risk of name clashes.
Unfortunately, some modules take this too far. Data::DPath is a good example. It has a really clear main function, dpath(), which it should export by default. Otherwise it's basically useless.
You can always turn off exporting with use Some::Module ();.
The reason is that some modules simply contain functions in them and they may or may not have chosen to export them by default, and that means they may need to be explicitly imported by the script to access directly or use a fully qualified name to access them. For example:
# in some script
use SomeModule;
# ...
SomeModule::some_function(...);
or
use SomeModule ('some_function');
# ...
some_function(...);
This can be the case if the module was not intended to be used in an object-oriented way, i.e. where no classes have been defined and lines such as my $obj = SomeModule->new() wouldn't work.
If the module has defined content in the EXPORT_OK array, it means that the client code will only get access to it if it "asks for it", rather than "automatically" when it's actually present in the EXPORT array.
Some modules automatically export their content by means of the #EXPORT array. This question and the Exporter docs have more detail on this.
Without you actually posting an MCVE, it's difficult to know what you've done in your Funcs.pm module that may be allowing you to import everything without using EXPORT and EXPORT_OK arrays. Perhaps you did not include the package Funcs; line in your module, as #JonathanLeffler suggested in the comments. Perhaps you did something else. Perl is one of those languages where people pride themselves in the TMTOWTDI mantra, often to a detrimental/counter-productive level, IMHO.
The 2nd example you presented is very different and fairly straightforward. When you have something like:
use WWW::Mechanize;
my $mech = new WWW::Mechanize;
$mech->get("http://www.google.com");
you're simply instantiating an object of type WWW::Mechanize and calling an instance method, called get, on it. There's no need to import an object's methods because the methods are part of the object itself. Modules looking to have an OOP approach are not meant to export anything. They're different situations.

How do I make PhpStorm suggest a list of predefined input variables?

How do I make PhpStorm suggest input variables ?
In Java/C# and the like (with VS/Eclipse), when I have a function that receives enum-input-variable, like:
void func(SomeEnum var);
Whenever I type func(, the editor kindly suggests all the available enums (of type SomeEnum). I look for this same functionality in PHP, when I have a predefined set of input options (like DB's tables).
Maybe with the use of Intellilang or these # tags (PHPDocs ?) I can predefine such list ?
Currently you cannot limit the possible options for code completion in this regard: PHP simply has no such "thing" similar to Enum. The only limitation you can do is limit by expected parameter type (e.g. int variable will not be offered when parameter expects an array).
I think this will be the correct ticket to look for: http://youtrack.jetbrains.com/issue/WI-854 and maybe http://youtrack.jetbrains.com/issue/WI-3623
Kind of related (for array indexes completion): http://youtrack.jetbrains.com/issue/WI-3423

Equivalent of abbrev-mode but for functions?

I'm a big fan of abbrev-mode and I'd like something a bit similar: you start typing and as soon as you enter some punctation (or just a space would be enough) it invokes a function (if I type space after a special abbreviation, of course, just like abbrev-mode does).
I definitely do NOT want to execute some function every single time I hit space...
So instead of expanding the abbreviation using abbrev-mode, it would run a function of my choice.
Of course it needs to be compatible with abbrev-mode, which I use all the time.
How can I get this behavior?
One approach could be to use pre-abbrev-expand-hook. I don't use abbrev mode myself, but it rather sounds as if you could re-use the abbrev mode machinery this way, and simply define some 'abbreviations' which expand to themselves (or to nothing?), and then you catch them in that hook and take whatever action you wish to.
The expand library is apparently related, and that provides expand-expand-hook, which may be another alternative?
edit: Whoops; pre-abbrev-expand-hook is obsolete since 23.1
abbrev-expand-functions is the correct variable to use:
Wrapper hook around `expand-abbrev'.
The functions on this special hook are called with one argument:
a function that performs the abbrev expansion. It should return
the abbrev symbol if expansion took place.
See M-x find-function RET expand-abbrev RET for the code, and you'll also want to read C-h f with-wrapper-hook RET to understand how this hook is used.
EDIT:
Your revised question adds some key details that my answer didn't address. phils has provided one way to approach this issue. Another would be to use yasnippet . You can include arbitrary lisp code in your snippet templates, so you could do something like this:
# -*- mode: snippet -*-
# name: foobars
# key: fbf
# binding: direct-keybinding
# --
`(foo-bar-for-the-win)`
You'd need to ensure your function didn't return anything, or it would be inserted in the buffer. I don't use abbrev-mode, so I don't know if this would introduce conflicts. yas/snippet takes a bit of experimenting to get it running, but it's pretty handy once you get it set up.
Original answer:
You can bind space to any function you like. You could bind all of the punctuation keys to the same function, or to different functions.
(define-key your-mode-map " " 'your-choice-function)
You probably want to do this within a custom mode map, so you can return to normal behaviour when you switch modes. Globally setting space to anything but self-insert would be unhelpful.
Every abbrev is composed of several elements. Among the main elements are the name (e.g. "fbf"), the expansion (any string you like), and the hook (a function that gets called). In your case it sounds like you want the expansion to be the empty string and simply specify your foo-bar-for-the-win as the hook.

api documentation and "value limits": do they match?

Do you often see in API documentation (as in 'javadoc of public functions' for example) the description of "value limits" as well as the classic documentation ?
Note: I am not talking about comments within the code
By "value limits", I mean:
does a parameter can support a null value (or an empty String, or...) ?
does a 'return value' can be null or is guaranteed to never be null (or can be "empty", or...) ?
Sample:
What I often see (without having access to source code) is:
/**
* Get all readers name for this current Report. <br />
* <b>Warning</b>The Report must have been published first.
* #param aReaderNameRegexp filter in order to return only reader matching the regexp
* #return array of reader names
*/
String[] getReaderNames(final String aReaderNameRegexp);
What I like to see would be:
/**
* Get all readers name for this current Report. <br />
* <b>Warning</b>The Report must have been published first.
* #param aReaderNameRegexp filter in order to return only reader matching the regexp
* (can be null or empty)
* #return array of reader names
* (null if Report has not yet been published,
* empty array if no reader match criteria,
* reader names array matching regexp, or all readers if regexp is null or empty)
*/
String[] getReaderNames(final String aReaderNameRegexp);
My point is:
When I use a library with a getReaderNames() function in it, I often do not even need to read the API documentation to guess what it does. But I need to be sure how to use it.
My only concern when I want to use this function is: what should I expect in term of parameters and return values ? That is all I need to know to safely setup my parameters and safely test the return value, yet I almost never see that kind of information in API documentation...
Edit:
This can influence the usage or not for checked or unchecked exceptions.
What do you think ? value limits and API, do they belong together or not ?
I think they can belong together but don't necessarily have to belong together. In your scenario, it seems like it makes sense that the limits are documented in such a way that they appear in the generated API documentation and intellisense (if the language/IDE support it).
I think it does depend on the language as well. For example, Ada has a native data type that is a "restricted integer", where you define an integer variable and explicitly indicate that it will only (and always) be within a certain numeric range. In that case, the datatype itself indicates the restriction. It should still be visible and discoverable through the API documentation and intellisense, but wouldn't be something that a developer has to specify in the comments.
However, languages like Java and C# don't have this type of restricted integer, so the developer would have to specify it in the comments if it were information that should become part of the public documentation.
I think those kinds of boundary conditions most definitely belong in the API. However, I would (and often do) go a step further and indicate WHAT those null values mean. Either I indicate it will throw an exception, or I explain what the expected results are when the boundary value is passed in.
It's hard to remember to always do this, but it's a good thing for users of your class. It's also difficult to maintain it if the contract the method presents changes (like null values are changed to no be allowed)... you have to be diligent also to update the docs when you change the semantics of the method.
Question 1
Do you often see in API documentation (as in 'javadoc of public functions' for example) the description of "value limits" as well as the classic documentation?
Almost never.
Question 2
My only concern when I want to use this function is: what should I expect in term of parameters and return values ? That is all I need to know to safely setup my parameters and safely test the return value, yet I almost never see that kind of information in API documentation...
If I used a function not properly I would expect a RuntimeException thrown by the method or a RuntimeException in another (sometimes very far) part of the program.
Comments like #param aReaderNameRegexp filter in order to ... (can be null or empty) seems to me a way to implement Design by Contract in a human-being language inside Javadoc.
Using Javadoc to enforce Design by Contract was used by iContract, now resurrected into JcontractS, that let you specify invariants, preconditions, postconditions, in more formalized way compared to the human-being language.
Question 3
This can influence the usage or not for checked or unchecked exceptions.
What do you think ? value limits and API, do they belong together or not ?
Java language doesn't have a Design by Contract feature, so you might be tempted to use Execption but I agree with you about the fact that you have to be aware about When to choose checked and unchecked exceptions. Probably you might use unchecked IllegalArgumentException, IllegalStateException, or you might use unit testing, but the major problem is how to communicate to other programmers that such code is about Design By Contract and should be considered as a contract before changing it too lightly.
I think they do, and have always placed comments in the header files (c++) arcordingly.
In addition to valid input/output/return comments, I also note which exceptions are likly to be thrown by the function (since I often want to use the return value for...well returning a value, I prefer exceptions over error codes)
//File:
// Should be a path to the teexture file to load, if it is not a full path (eg "c:\example.png") it will attempt to find the file usign the paths provided by the DataSearchPath list
//Return: The pointer to a Texture instance is returned, in the event of an error, an exception is thrown. When you are finished with the texture you chould call the Free() method.
//Exceptions:
//except::FileNotFound
//except::InvalidFile
//except::InvalidParams
//except::CreationFailed
Texture *GetTexture(const std::string &File);
#Fire Lancer: Right! I forgot about exception, but I would like to see them mentioned, especially the unchecked 'runtime' exception that this public method could throw
#Mike Stone:
you have to be diligent also to update the docs when you change the semantics of the method.
Mmmm I sure hope that the public API documentation is at the very least updated whenever a change -- that affects the contract of the function -- takes place. If not, those API documentations could be drop altogether.
To add food to yours thoughts (and go with #Scott Dorman), I just stumble upon the future of java7 annotations
What does that means ? That certain 'boundary conditions', rather than being in the documentation, should be better off in the API itself, and automatically used, at compilation time, with appropriate 'assert' generated code.
That way, if a '#CheckForNull' is in the API, the writer of the function might get away with not even documenting it! And if the semantic change, its API will reflect that change (like 'no more #CheckForNull' for instance)
That kind of approach suggests that documentation, for 'boundary conditions', is an extra bonus rather than a mandatory practice.
However, that does not cover the special values of the return object of a function. For that, a complete documentation is still needed.