Answers.Body: <p>Absolutely, just add the app directory as a external library.</p>
  
  <ol>
  <li>Double click on the 'external libraries'.</li>
  <li>Add the interpreter</li>
  <li>Include the path to the 'app' directory</li>
  </ol>
  
  <p><img src="https://i.sstatic.net/ZUoBy.png" alt="enter image description here"></p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-28T18:40:38.963Z
Answers.Text: Is this the only solution for getting this to work? Additionally, I'm a little confused. In your first sentence you said the "app" directory and that's what appears to be illustrated in your screenshot but in your numbered instructions you say the "craft" directory.
Answers.UserDisplayName: Tyler Willingham
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-28T18:41:49.457Z
Answers.Text: Typo, I will correct it.
Answers.UserDisplayName: Jason McCallister
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-28T19:09:17.447Z
Answers.Text: Also, to enable phpstorm to auto complete - you have to reference the library (craft) so it knows where to load the code from.
Answers.UserDisplayName: Jason McCallister
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-30T20:17:02.770Z
Answers.Text: Is this supposed to work for third-party plugins' services? I'm not able to get that working.
Answers.UserDisplayName: Tyler Willingham
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-30T21:21:28.270Z
Answers.Text: I'm actually not sure how that would work for a plugin. It works in Craft by defining the property in the PHPDoc in WebApp.php.  So @property AssetsService $assets, lets PHPStorm know that there exists an AssetsService object off of craft()->assets.  And it's not like we can add a hook for the PHPDoc.  Maybe through some crazy reflection magic, but it'd be super hackey.
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-31T16:03:48.107Z
Answers.Text: @BradBell Can you make that an answer so I can select it as correct? Jason's answer was correct per my original title but incorrect per the description (I recently corrected the title).
Answers.UserDisplayName: Tyler Willingham
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-31T16:54:50.820Z
Answers.Text: @TylerWillingham Done!
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-28T17:17:40.797Z
Answers.LastActivityDate: 2014-07-28T18:42:06.360Z
Answers.LastEditDate: 2014-07-28T18:42:06.360Z
Answers.UserDisplayName: Jason McCallister
Answers.Body: <p>I handled it by adding a global function and singleton object similar to Craft's WebApp. All of my plugin's services are access from my custom global function myPlugin() while Craft's services continue to be started from the craft() global function. In the doc block for the new object, I specify properties for each service. Each new service must be added by hand, but all members of that service are recognized by the IDE. </p>
  
  <p>This should work across all IDEs (including PHPStorm where this was developed). </p>
  
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  namespace Craft;
  /**
   * Class MyPlugin
   * @package Craft
   */
  
  /**
   * @property MyPlugin_CategoriesService $categories MyPlugin Categories Service
   * @property MyPlugin_TriviaService     $trivia     MyPlugin Trivia Service
   */
  class MyPlugin {
  
      public function __get($memberName)
      {
          $craftName = 'myPlugin_' . strtolower($memberName);
          return craft()-&gt;$craftName;
      }
  
      /**
       * Return singleton instance of the rantAPI service manager
       * @return MyPlugin
       */
      public static function app()
      {
          static $inst = null;
          if ( $inst === null) {
              $inst = new MyPlugin();
          }
          return $inst;
      }
  }
  
  
  /**
   * Returns the myPlugin equivalent to webApp class that serves up all the services.
   *
   * @return MyPlugin
   */
  function myPlugin()
  {
      return MyPlugin::app();
  }
  </code></pre>
  
  <p>In my controller, I reference my services and craft's services in the following way.</p>
  
  <pre class="lang-php prettyprint-override"><code>$parentEntry = craft()-&gt;entries-&gt;getEntryById(999);
  $triviaToAdd = myPlugin()-&gt;trivia-&gt;getByKeyword('nerds');
  </code></pre>
  
  <p>In the example above, both entries and trivia are recognized as valid objects and their methods are available for intelligent code completion. </p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-08-05T20:10:17.323Z
Answers.Text: Nice and clever!
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-08-05T18:45:09.673Z
Answers.LastActivityDate: 2014-08-05T20:00:03.887Z
Answers.LastEditDate: 2014-08-05T20:00:03.887Z
Answers.UserDisplayName: Dan Eichholz
Answers.Body: <p>I'm kinda late to the party here but Brandon suggested I add the technique I use to this thread.</p>
  
  <p>What I do in order for PHPStorm to resolve my own <code>craft()-&gt;myService</code> is to not use that at all because you can't type hint services that get created at runtime. What I do instead, is to declare a function with the name of my plugin that is properly type hinted.</p>
  
  <p>Let's say that I have a plugin called <code>PatrolPlugin</code> with a service called <code>PatrolService</code> which has a method called <code>protect()</code>. If I want to navigate to the method definition/declaration for <code>PatrolService.protect()</code>, I would do something like this.</p>
  
  <ol>
  <li>Create a properly type hinted service getter, this can be a global function or a static method in your plugin class.</li>
  </ol>
  
  <pre class="lang-php prettyprint-override"><code>/**
   * Tells PHPStorm or any other smart IDE that patrol() returns my service
   *
   * @return PatrolService
   */
  function patrol()
  {
      return Craft::app()-&gt;getComponent('patrol');
  }
  </code></pre>
  
  <ol start="2">
  <li>Call that function/method instead of using <code>craft()-&gt;patrol</code></li>
  </ol>
  
  <pre class="lang-php prettyprint-override"><code>patrol()-&gt;protect()
  </code></pre>
  
  <ol start="3">
  <li>Place the cursor inside <code>protect</code> and go to definition.</li>
  </ol>
  
  <p>That's what I do anyways, and it works for me.</p>
  
  <hr>
  
  <p>If I had other services that I wanted type hinted, I can just add them as properties of the main service.</p>
  
  <pre class="lang-php prettyprint-override"><code>/**
   * @property Patrol_OtherService $other
   */
  class PatrolService extends BaseApplicationComponent
  {
      public $other;
  
      public function init()
      {
          $this-&gt;other = Craft::app()-&gt;getComponent('patrol_other');
      }
  }
  </code></pre>
  
  <p><strong>Note:</strong> I'm using <code>Craft::app()-&gt;getComponent('service')</code> because it is a bit faster than <code>craft()-&gt;service</code> but they are basically the same.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-12-18T21:27:59.927Z
Answers.LastActivityDate: 2014-12-18T21:27:59.927Z
Answers.UserDisplayName: Selvin Ortiz
Answers.Body: <p>I'm actually not sure how it would work if you're trying to reference another plugin's services.</p>
  
  <p>It works in Craft by defining the property in the PHPDoc in <code>WebApp.php</code>.</p>
  
  <pre><code>@property AssetsService $assets
  </code></pre>
  
  <p>That lets PHPStorm know that there exists an AssetsService object off of <code>craft()-&gt;assets</code>.</p>
  
  <p>And it's not like we can add a hook for the PHPDoc so plugins can inject their own... maybe through some crazy reflection magic, but it'd be super hackey.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-22T15:13:11.370Z
Answers.Text: I've added it to my WebApp.php file and autocomplete still doesn't find my plugin service. Any ideas?
Answers.UserDisplayName: Sandy D.
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-22T15:19:42.023Z
Answers.Text: If you're on the latest version of PhpStorm, there is a bug preventing most autocompletion. https://youtrack.jetbrains.com/issue/WI-28394
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-22T15:22:36.320Z
Answers.Text: I am using the latest version. =(
Answers.UserDisplayName: Sandy D.
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-10-22T16:15:25.140Z
Answers.Text: Me too. :(  Feel free to leave a comment on that bug report. :)
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-03-07T15:02:26.037Z
Answers.Text: @SandyD. This is now fixed on the EAP build of PHPStorm! [Link to EAP build](https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program)
Answers.UserDisplayName: Merlin
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-31T16:54:37.437Z
Answers.LastActivityDate: 2014-07-31T16:54:37.437Z
Answers.UserDisplayName: Brad Bell
Body: <p>It would make my day to be able to have PHPStorm recognize third-party services. Has anyone figured out how to get this working yet?</p>
  
Tags: <plugin-development>
Title: Has anyone been able to get auto-complete working with plugins + PHPStorm?
ThreadText: # Has anyone been able to get auto-complete working with plugins + PHPStorm?
  
  (Asked by: username_0 on 2014-07-28)
  
  It would make my day to be able to have PHPStorm recognize third-party services. Has anyone figured out how to get this working yet?
  
  **Tags:** plugin-development
  
  
  ---
  
  ## 4 answers
  
  ### Answer by username_2 on 2014-07-31. Score: 5 | Accepted answer
  
  I'm actually not sure how it would work if you're trying to reference another plugin's services.
  
  It works in Craft by defining the property in the PHPDoc in `WebApp.php`.
  
  ```
  @property AssetsService $assets
  
  ```
  
  That lets PHPStorm know that there exists an AssetsService object off of `craft()->assets`.
  
  And it's not like we can add a hook for the PHPDoc so plugins can inject their own... maybe through some crazy reflection magic, but it'd be super hackey.
  
  > **Comments:**
  > **username_5**: I've added it to my WebApp.php file and autocomplete still doesn't find my plugin service. Any ideas?  
  > **username_2**: If you're on the latest version of PhpStorm, there is a bug preventing most autocompletion. https://youtrack.jetbrains.com/issue/WI-28394  
  > **username_5**: I am using the latest version. =(  
  > **username_2**: Me too. :(  Feel free to leave a comment on that bug report. :)  
  > **username_6**: @SandyD. This is now fixed on the EAP build of PHPStorm! [Link to EAP build](https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program)  
  
  ---
  
  ### Answer by username_1 on 2014-07-28. Score: 6
  
  Absolutely, just add the app directory as a external library.
  
  1. Double click on the 'external libraries'.
  2. Add the interpreter
  3. Include the path to the 'app' directory
  
  ![enter image description here](https://i.sstatic.net/ZUoBy.png)
  
  > **Comments:**
  > **username_0**: Is this the only solution for getting this to work? Additionally, I'm a little confused. In your first sentence you said the "app" directory and that's what appears to be illustrated in your screenshot but in your numbered instructions you say the "craft" directory.  
  > **username_1**: Typo, I will correct it.  
  > **username_1**: Also, to enable phpstorm to auto complete - you have to reference the library (craft) so it knows where to load the code from.  
  > **username_0**: Is this supposed to work for third-party plugins' services? I'm not able to get that working.  
  > **username_2**: I'm actually not sure how that would work for a plugin. It works in Craft by defining the property in the PHPDoc in WebApp.php.  So @property AssetsService $assets, lets PHPStorm know that there exists an AssetsService object off of craft()->assets.  And it's not like we can add a hook for the PHPDoc.  Maybe through some crazy reflection magic, but it'd be super hackey.  
  > **username_0**: @username_2 Can you make that an answer so I can select it as correct? username_1's answer was correct per my original title but incorrect per the description (I recently corrected the title).  
  > **username_2**: @username_0 Done!  
  
  ---
  
  ### Answer by username_3 on 2014-08-05. Score: 6
  
  I handled it by adding a global function and singleton object similar to Craft's WebApp. All of my plugin's services are access from my custom global function myPlugin() while Craft's services continue to be started from the craft() global function. In the doc block for the new object, I specify properties for each service. Each new service must be added by hand, but all members of that service are recognized by the IDE.
  
  This should work across all IDEs (including PHPStorm where this was developed).
  
  ```php
  <?php
  namespace Craft;
  /**
   * Class MyPlugin
   * @package Craft
   */
  
  /**
   * @property MyPlugin_CategoriesService $categories MyPlugin Categories Service
   * @property MyPlugin_TriviaService     $trivia     MyPlugin Trivia Service
   */
  class MyPlugin {
  
      public function __get($memberName)
      {
          $craftName = 'myPlugin_' . strtolower($memberName);
          return craft()->$craftName;
      }
  
      /**
       * Return singleton instance of the rantAPI service manager
       * @return MyPlugin
       */
      public static function app()
      {
          static $inst = null;
          if ( $inst === null) {
              $inst = new MyPlugin();
          }
          return $inst;
      }
  }
  
  /**
   * Returns the myPlugin equivalent to webApp class that serves up all the services.
   *
   * @return MyPlugin
   */
  function myPlugin()
  {
      return MyPlugin::app();
  }
  
  ```
  
  In my controller, I reference my services and craft's services in the following way.
  
  ```php
  $parentEntry = craft()->entries->getEntryById(999);
  $triviaToAdd = myPlugin()->trivia->getByKeyword('nerds');
  
  ```
  
  In the example above, both entries and trivia are recognized as valid objects and their methods are available for intelligent code completion.
  
  > **Comments:**
  > **username_2**: Nice and clever!  
  
  ---
  
  ### Answer by username_4 on 2014-12-18. Score: 3
  
  I'm kinda late to the party here but Brandon suggested I add the technique I use to this thread.
  
  What I do in order for PHPStorm to resolve my own `craft()->myService` is to not use that at all because you can't type hint services that get created at runtime. What I do instead, is to declare a function with the name of my plugin that is properly type hinted.
  
  Let's say that I have a plugin called `PatrolPlugin` with a service called `PatrolService` which has a method called `protect()`. If I want to navigate to the method definition/declaration for `PatrolService.protect()`, I would do something like this.
  
  1. Create a properly type hinted service getter, this can be a global function or a static method in your plugin class.
  
  ```php
  /**
   * Tells PHPStorm or any other smart IDE that patrol() returns my service
   *
   * @return PatrolService
   */
  function patrol()
  {
      return Craft::app()->getComponent('patrol');
  }
  
  ```
  
  2. Call that function/method instead of using `craft()->patrol`
  
  ```php
  patrol()->protect()
  
  ```
  
  3. Place the cursor inside `protect` and go to definition.
  
  That's what I do anyways, and it works for me.
  
  ---
  
  If I had other services that I wanted type hinted, I can just add them as properties of the main service.
  
  ```php
  /**
   * @property Patrol_OtherService $other
   */
  class PatrolService extends BaseApplicationComponent
  {
      public $other;
  
      public function init()
      {
          $this->other = Craft::app()->getComponent('patrol_other');
      }
  }
  
  ```
  
  **Note:** I'm using `Craft::app()->getComponent('service')` because it is a bit faster than `craft()->service` but they are basically the same.
  
  
  ---
  
  