Search code examples
javascriptcss-selectorsphpstormcode-completion

How to tell PhpStorm / WebStorm that some argument has to be a CSS selector?


I want to use jQuery-like shorthands for the JavaScript methods querySelector and querySelectorAll. At least I've already managed that PhpStorm understands the return results on completion. However, I've got no clue how to get completion work in the CSS-selector string argument.

/** @typedef {function (selectors:string):NodeList|null} FnQuerySelectorAll */
/** @typedef {function (selectors:string):Element      } FnQuerySelector    */

(d =>
{
  const
    /** @type FnQuerySelectorAll */ 
    $  = (Document.prototype.$  = Document.prototype.querySelectorAll).bind(d),

    /** @type FnQuerySelector    */
    $1 = (Document.prototype.$1 = Document.prototype.querySelector   ).bind(d)
  ;
  Element.prototype.$           = Element .prototype.querySelectorAll;
  Element.prototype.$1          = Element .prototype.querySelector   ;
  // ...
})(document)

When I type document.$(', actually, I do get selector completions.
When I type $(', it does not behave in the same way.

PhpStorm does not recognize the functions built by the bind method. I'm not very familiar with JSDoc. Is there any possibility to tell PhpStorm that the string argument has to be a CSS selector or the whole function is an alias for another one?


Solution

  • I've now managed the issue by configuring PhpStorm.

    • Open the PhpStorm settings.
    • Navigate to "Editor > Language Injections".
    • Edit the entry "js:DOM element selectors".

    The original "Places Pattern" was:

    + jsArgument(jsReferenceExpression().withReferenceNames("querySelector", "querySelectorAll", "closest"), 0)
    

    Change it to:

    + jsArgument(jsReferenceExpression().withReferenceNames("querySelector", "querySelectorAll", "closest", "$", "$1"), 0)
    

    Now PphStorm recognizes the first argument of the functions $ and $1 as a CSS selector string.

    Note: Although this settings page is marked as per project basis, the scope of the rule has the scope IDE by default. Thus it will affect all other projects as well.

    As mentioned by @LazyOne, it could be more desirable to duplicate the original rule and change your own copy to:

    + jsArgument(jsReferenceExpression().withReferenceNames("$", "$1"), 0)
    

    You can move your modified custom copy to project scope by using the buttons above the list if you want.