From aeff76bc3c747602fa175437e183f47284e9fca0 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 5 Apr 2023 16:02:44 +0200 Subject: [PATCH] Add more examples to plugin_services.md --- .../plugin_structure/plugin_services.md | 234 +++++++++++++++--- 1 file changed, 193 insertions(+), 41 deletions(-) diff --git a/topics/basics/plugin_structure/plugin_services.md b/topics/basics/plugin_structure/plugin_services.md index 5b9f5c5a5..89db6faaf 100644 --- a/topics/basics/plugin_structure/plugin_services.md +++ b/topics/basics/plugin_structure/plugin_services.md @@ -1,7 +1,7 @@ -# Services - +# Services + Registering and using on-demand services to encapsulate plugin functionality. A _service_ is a plugin component loaded on demand when your plugin calls the `getService()` method of corresponding [`ComponentManager`](%gh-ic%/platform/extensions/src/com/intellij/openapi/components/ComponentManager.java) instance (see [Types](#types)). @@ -29,7 +29,7 @@ To improve startup performance, avoid any heavy initializations in the construct > Using constructor injection of dependency services is deprecated (and not supported in [](#light-services)) for performance reasons. > -> Other dependencies must be [acquired only when needed](#retrieving-a-service) in all corresponding methods (see `someServiceMethod()` in [Project Service Sample](#project-service-sample)). +> Other dependencies must be [acquired only when needed](#retrieving-a-service) in all corresponding methods (see `doSomething()` in [Light Service Examples](#light-service-examples)). > > Use inspection Plugin DevKit | Code | Non-default constructors for service and extension class to verify code. > @@ -49,7 +49,78 @@ Restrictions: * Constructor injection of dependency services is not supported. * If application-level service is a [PersistentStateComponent](persisting_state_of_components.md), roaming must be disabled (`roamingType = RoamingType.DISABLED`). -See [Project-Level Service](#project-service-sample) below for a sample. +### Examples +{#light-service-examples} + +Application-level light service: + + + + + +```java +@Service +public final class MyAppService { + public void doSomething(String param) { + // ... + } +} +``` + + + + + +```kotlin +@Service +class MyAppService { + fun doSomething(param: String) { + // ... + } +} +``` + + + + +Project-level light service example: + + + + + +```java +@Service(Service.Level.PROJECT) +public final class MyProjectService { + private final Project myProject; + + public MyProjectService(Project project) { + myProject = project; + } + + public void doSomething(String param) { + String projectName = myProject.getName(); + // ... + } +} +``` + + + + + +```kotlin +@Service(Service.Level.PROJECT) +class MyProjectService(private val project: Project) { + fun doSomething(param: String) { + val projectName = project.name + // ... + } +} +``` + + + ## Declaring a Service @@ -64,18 +135,122 @@ If `serviceInterface` isn't specified, it's supposed to have the same value as ` To provide custom implementation for test/headless environment, specify `testServiceImplementation`/`headlessImplementation` additionally. -plugin.xml +### Example + + + + + + +Application-level service: + +- Interface: + + ```java + public interface MyAppService { + void doSomething(String param); + } + ``` + +- Implementation: + + ```java + public class MyAppServiceImpl implements MyAppService { + @Override + public void doSomething(String param) { + // ... + } + } + ``` + +Project-level service: + +- Interface: + + ```java + public interface MyProjectService { + void doSomething(String param); + } + ``` + +- Implementation: + + ```java + public class MyProjectServiceImpl { + private final Project myProject; + + public MyProjectServiceImpl(Project project) { + myProject = project; + } + + public void doSomething(String param) { + String projectName = myProject.getName(); + // ... + } + } + ``` + + + + +Application-level service: + +- Interface: + + ```kotlin + interface MyAppService { + fun doSomething(param: String) + } + ``` + +- Implementation: + + ```kotlin + class MyAppServiceImpl : MyAppService { + override fun doSomething(param: String) { + // ... + } + } + ``` + +Project-level service: + +- Interface: + + ```kotlin + interface MyProjectService { + fun doSomething(param: String) + } + ``` + +- Implementation: + + ```kotlin + class MyProjectServiceImpl(private val project: Project) + : MyProjectService { + + fun doSomething(param: String) { + val projectName = project.name + // ... + } + } + ``` + + + + +Registration in plugin.xml: ```xml + serviceInterface="com.example.MyAppService" + serviceImplementation="com.example.MyAppServiceImpl"/> + serviceInterface="com.example.MyProjectService" + serviceImplementation="com.example.MyProjectServiceImpl"/> ``` @@ -92,30 +267,31 @@ To provide custom implementation for test/headless environment, specify `testSer Getting service doesn't need a read action and can be performed from any thread. If a service is requested from several threads, it will be initialized in the first thread, and other threads will be blocked until it is fully initialized. - - + + ```java -MyApplicationService applicationService = ApplicationManager.getApplication() - .getService(MyApplicationService.class); +MyAppService applicationService = + ApplicationManager.getApplication().getService(MyAppService.class); -MyProjectService projectService = project.getService(MyProjectService.class); +MyProjectService projectService = + project.getService(MyProjectService.class); ``` Service implementations can wrap these calls with convenient static `getInstance()` or `getInstance(Project)` method: ```java -MyApplicationService applicationService = MyApplicationService.getInstance(); +MyAppService applicationService = MyAppService.getInstance(); MyProjectService projectService = MyProjectService.getInstance(project); ``` - + ```kotlin -val applicationService = service() +val applicationService = service() val projectService = project.service() ``` @@ -129,30 +305,6 @@ val projectService = project.service() -## Project Service Sample - -This minimal sample shows [Light Service](#light-services) `ProjectService` interacting with another project-level service `AnotherService` (not shown here). - -ProjectService.java - -```java -@Service(Service.Level.PROJECT) -public final class ProjectService { - - private final Project myProject; - - public ProjectService(Project project) { - myProject = project; - } - - public void someServiceMethod(String parameter) { - AnotherService anotherService = myProject.getService(AnotherService.class); - String result = anotherService.anotherServiceMethod(parameter, false); - // do some more stuff - } -} -``` - ## Sample Plugin To clarify how to use services, consider the **maxOpenProjects** sample plugin available in the [code samples](%gh-sdk-samples%/max_opened_projects).