From c7fca5b316ccd51828f18e4729a5e4208b6cb11f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Tue, 1 Oct 2024 14:24:13 +0200 Subject: [PATCH] plugin_services.md: smaller improvements/clarifications --- .../plugin_structure/plugin_services.md | 56 +++++++++++++------ 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/topics/basics/plugin_structure/plugin_services.md b/topics/basics/plugin_structure/plugin_services.md index eedd9505a..c95227ea9 100644 --- a/topics/basics/plugin_structure/plugin_services.md +++ b/topics/basics/plugin_structure/plugin_services.md @@ -29,6 +29,7 @@ For the latter two, a separate instance of the service is created for each insta {id="moduleServiceNote"} #### Constructor + {#ctor} To improve startup performance, avoid any heavy initializations in the constructor. @@ -52,24 +53,27 @@ When using [](kotlin_coroutines.md), a distinct service [scope](coroutine_scopes ## Light Services -A service not going to be overridden/exposed as API to other plugins does not need to be registered in [plugin.xml](plugin_configuration_file.md) (see [](#declaring-a-service)). -Instead, annotate service class with [`@Service`](%gh-ic%/platform/core-api/src/com/intellij/openapi/components/Service.java) (see [](#examples)). -The service instance will be created in scope according to the caller (see [](#retrieving-a-service)). +A service not going to be overridden or exposed as API to other plugins does not need to be registered in [plugin.xml](plugin_configuration_file.md) (see [](#declaring-a-service)). +Instead, annotate the service class with [`@Service`](%gh-ic%/platform/core-api/src/com/intellij/openapi/components/Service.java) (see [](#examples)). +The service instance will be created in the scope according to the caller (see [](#retrieving-a-service)). ### Light Service Restrictions -* None of these attributes is allowed: `os`, `client`, `overrides`, `id`, `preload`. +* None of these attributes/restrictions (available for [registration of non-light services](#declaring-a-service)) is allowed: `id`, `os`, `client`, `overrides`, `configurationSchemaKey`/`preload` (Internal API). +* There is no separate headless/test implementation required. * Service class must be `final`. * [Constructor injection](#ctor) 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`). +* If an application-level service is a [PersistentStateComponent](persisting_state_of_components.md), roaming must be disabled (`roamingType = RoamingType.DISABLED`). + +Use these inspections to verify above restrictions and highlight non-light services that can be converted (2023.3): -Use these inspections to verify these and highlight services that can be converted (2023.3): - Plugin DevKit | Code | Light service must be final - Plugin DevKit | Code | Mismatch between light service level and its constructor - Plugin DevKit | Code | A service can be converted to a light one and corresponding Plugin DevKit | Plugin descriptor | A service can be converted to a light one for plugin.xml ### Examples +{id="lightServiceExamples"} @@ -79,19 +83,24 @@ Use these inspections to verify these and highlight services that can be convert Application-level light service: ```java + @Service public final class MyAppService { + public void doSomething(String param) { // ... } + } ``` Project-level light service example: ```java + @Service(Service.Level.PROJECT) public final class MyProjectService { + private final Project myProject; MyProjectService(Project project) { @@ -102,6 +111,7 @@ public final class MyProjectService { String projectName = myProject.getName(); // ... } + } ``` @@ -140,18 +150,25 @@ class MyProjectService(private val project: Project) { To register a non-[Light Service](#light-services), distinct extension points are provided for each type: -* `com.intellij.applicationService` - application-level service -* `com.intellij.projectService` - project-level service -* `com.intellij.moduleService` - module-level service (not recommended, see [Note](#types)) +* `com.intellij.applicationService` – application-level service +* `com.intellij.projectService` – project-level service +* `com.intellij.moduleService` – module-level service (not recommended, see [Note](#types)) -To expose service API, create a separate class for `serviceInterface` and extend it in corresponding class registered in `serviceImplementation`. -If `serviceInterface` isn't specified, it's supposed to have the same value as `serviceImplementation`. +The service implementation is specified in the required `serviceImplementation` attribute. + +### Service API + +To expose a service's API, create a separate class for `serviceInterface` and extend it in the corresponding class registered in `serviceImplementation`. +If `serviceInterface` isn't specified, it is supposed to have the same value as `serviceImplementation`. Use inspection Plugin DevKit | Plugin descriptor | Plugin.xml extension registration to highlight redundant `serviceInterface` declarations. -To provide a custom implementation for test/headless environment, specify `testServiceImplementation`/`headlessImplementation` additionally. +### Additional Attributes -### Example +A service can be restricted to a certain OS via the `os` attribute. +To provide a custom implementation for test or headless environment, specify `testServiceImplementation` or `headlessImplementation` respectively. + +### Examples @@ -204,6 +221,7 @@ Project-level service: } } ``` + @@ -250,22 +268,25 @@ Project-level service: } } ``` + Registration in plugin.xml: + ```xml + + serviceInterface="com.example.MyAppService" + serviceImplementation="com.example.MyAppServiceImpl"/> + serviceInterface="com.example.MyProjectService" + serviceImplementation="com.example.MyProjectServiceImpl"/> ``` @@ -313,6 +334,7 @@ val applicationService = service() val projectService = project.service() ``` +