Skip to content

Commit 78e27ef

Browse files
authored
Merge pull request #321 from mercari/improve-jetbrains-plugin
feat(jetbrains-plugin): add semantic tokens support and enhance import path configuration UI
2 parents 03a12f3 + 507a86b commit 78e27ef

File tree

13 files changed

+740
-130
lines changed

13 files changed

+740
-130
lines changed

lsp/client/jetbrains/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
.idea
33
.qodana
44
build
5+
.intellijPlatform
6+
.kotlin

lsp/client/jetbrains/CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,45 @@
33
# gRPC Federation Changelog
44

55
## [Unreleased]
6+
7+
### Added
8+
- New list-based UI for Proto Import Paths configuration
9+
- Enable/disable toggle for individual import paths
10+
- File browser dialog for adding and editing paths
11+
- Path validation feature to check if directories exist
12+
- Variable expansion support for `~/` and `${PROJECT_ROOT}`
13+
- Toolbar buttons for add, remove, and reorder operations
14+
- "Validate Paths" button to verify all configured paths
15+
- Semantic tokens support for enhanced syntax highlighting of gRPC Federation annotations
16+
- Token type mappings for proper colorization of proto elements
17+
- Explicit semantic tokens request for proto files
18+
19+
### Changed
20+
- Redesigned settings interface from single text field to table-based UI
21+
- Improved path management with better visual feedback
22+
- Enhanced user experience for managing multiple import paths
23+
- Migrated settings storage format from simple string list to structured entries with enable/disable state
24+
- Updated to IntelliJ Platform Gradle Plugin 2.7.2 (latest)
25+
- Updated to Platform Version 2024.3.3 with Kotlin 2.1.0
26+
- Updated JVM toolchain from Java 17 to Java 21 (recommended for 2024.3.3)
27+
- Changed LSP server descriptor from ProjectWideLspServerDescriptor to LspServerDescriptor for proper semantic tokens support
28+
29+
### Fixed
30+
- Issue with paths containing spaces in the previous text field approach
31+
- Better handling of empty and invalid path entries
32+
- Checkbox display issue in the Enabled column with explicit renderer and editor
33+
- Diagnostic messages containing HTML tags (like `<input>`) are now properly escaped to prevent UI rendering issues
34+
35+
### Deprecated
36+
- `importPaths` field in settings storage (will be removed in v0.3.0)
37+
- Automatic migration: Existing configurations will be automatically converted to the new format
38+
- The plugin maintains backward compatibility by reading from both old and new formats
39+
- Only the new `importPathEntries` format will be supported from v0.3.0 onwards
40+
41+
## [0.1.0]
42+
43+
### Added
44+
- Initial release of gRPC Federation IntelliJ plugin
45+
- Basic Language Server Protocol (LSP) integration
46+
- Proto import paths configuration
47+
- Support for `.proto` files with gRPC Federation annotations

lsp/client/jetbrains/README.md

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,90 @@
11
<!-- Plugin description -->
22
# gRPC Federation Language Server for JetBrains
3-
The gRPC Federation Language Server for JetBrains is a plugin designed for JetBrains IDEs to integrate with the gRPC Federation language server, offering various useful functionalities such as code completion.
3+
4+
The gRPC Federation Language Server for JetBrains is a plugin designed for JetBrains IDEs to integrate with the gRPC Federation language server, providing enhanced development experience for Protocol Buffer files with gRPC Federation annotations.
45

56
## Features
67

7-
Currently, the following features are supported:
8+
- **Go to Definition** - Navigate to proto message and field definitions
9+
- **Diagnostics** - Real-time error detection and validation
10+
- **Code Completion** - Intelligent suggestions for gRPC Federation annotations
11+
12+
## Requirements
813

9-
- Goto Definition
10-
- Diagnostics
11-
- Code Completion
14+
- **IntelliJ IDEA Ultimate** 2023.3 or newer (This plugin requires Ultimate Edition)
15+
- **grpc-federation-language-server** installed and available in PATH
1216

1317
## Installation
14-
To utilize the plugin, `grpc-federation-language-server` must be accessible in the path. If Go is available, execute the following command to install it:
18+
19+
### Step 1: Install the Language Server
20+
The plugin requires `grpc-federation-language-server` to be accessible in the system PATH. If Go is available, install it with:
1521

1622
```console
1723
$ go install github.com/mercari/grpc-federation/cmd/grpc-federation-language-server@latest
1824
```
1925

20-
Afterward, install the plugin from the Marketplace.
26+
Verify the installation:
27+
```console
28+
$ which grpc-federation-language-server
29+
```
30+
31+
### Step 2: Install the Plugin
32+
Install the plugin from JetBrains Marketplace:
2133

22-
`Settings/Preferences` > `Plugins` > `Marketplace` > `Search for "gRPC Federation"` > `Install`
34+
1. Open **Settings/Preferences****Plugins**
35+
2. Select **Marketplace** tab
36+
3. Search for **"gRPC Federation"**
37+
4. Click **Install** and restart the IDE
2338

2439
## Configuration
25-
For `grpc-federation-language-server` to function properly, provide proto import paths to import dependent proto files.
2640

27-
`Settings/Preferences` > `Tools` > `gRPC Federation` > `Proto Import Paths`
41+
### Setting Import Paths
42+
Configure proto import paths for the language server to resolve dependencies:
43+
44+
1. Navigate to **Settings/Preferences****Tools****gRPC Federation**
45+
2. In the **Proto Import Paths** section:
46+
- Click **+** to add a new path
47+
- Use the file browser to select directories
48+
- Enable/disable paths using checkboxes
49+
- Reorder paths using ↑/↓ buttons
50+
- Click **Validate Paths** to verify all directories exist
51+
52+
### Supported Path Variables
53+
54+
- `~/` - User's home directory
55+
- `${PROJECT_ROOT}` - Current project root directory
56+
57+
Example paths:
58+
```
59+
/usr/local/include
60+
${PROJECT_ROOT}/proto
61+
~/workspace/shared-protos
62+
```
63+
64+
## Troubleshooting
65+
66+
### Language Server Not Found
67+
If you see "grpc-federation-language-server not found" error:
68+
1. Ensure the language server is installed (see Installation section)
69+
2. Check if it's in your PATH: `which grpc-federation-language-server`
70+
3. Restart the IDE after installation
71+
72+
### Proto Files Not Recognized
73+
If proto files are not being analyzed:
74+
1. Ensure the file extension is `.proto`
75+
2. Check that import paths are correctly configured
76+
3. Validate paths using the **Validate Paths** button
77+
4. Check the IDE logs: **Help****Show Log in Finder/Explorer**
78+
79+
### Import Resolution Issues
80+
If imports are not being resolved:
81+
1. Add all necessary proto directories to import paths
82+
2. Ensure paths are in the correct order (more specific paths first)
83+
3. Check that all proto dependencies are available
84+
85+
## Support
86+
87+
- **Issues**: [GitHub Issues](https://github.com/mercari/grpc-federation/issues)
88+
- **Documentation**: [gRPC Federation Documentation](https://github.com/mercari/grpc-federation)
89+
2890
<!-- Plugin description end -->

lsp/client/jetbrains/build.gradle.kts

Lines changed: 72 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import org.jetbrains.changelog.Changelog
22
import org.jetbrains.changelog.markdownToHTML
3+
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
34

45
fun properties(key: String) = providers.gradleProperty(key)
56
fun environment(key: String) = providers.environmentVariable(key)
67

78
plugins {
89
id("java") // Java support
910
alias(libs.plugins.kotlin) // Kotlin support
10-
alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Plugin
11+
alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Platform Plugin
1112
alias(libs.plugins.changelog) // Gradle Changelog Plugin
1213
alias(libs.plugins.qodana) // Gradle Qodana Plugin
1314
alias(libs.plugins.kover) // Gradle Kover Plugin
@@ -19,66 +20,54 @@ version = properties("pluginVersion").get()
1920
// Configure project's dependencies
2021
repositories {
2122
mavenCentral()
23+
24+
// IntelliJ Platform Gradle Plugin Repositories Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-repositories-extension.html
25+
intellijPlatform {
26+
defaultRepositories()
27+
}
2228
}
2329

2430
// Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog
2531
dependencies {
2632
// implementation(libs.annotations)
33+
34+
// IntelliJ Platform Gradle Plugin Dependencies Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html
35+
intellijPlatform {
36+
create(properties("platformType"), properties("platformVersion"))
37+
38+
// Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file.
39+
bundledPlugins(properties("platformPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) })
40+
41+
pluginVerifier()
42+
zipSigner()
43+
testFramework(TestFrameworkType.Platform)
44+
}
2745
}
2846

2947
// Set the JVM language level used to build the project.
3048
kotlin {
31-
jvmToolchain(17)
32-
}
33-
34-
// Configure Gradle IntelliJ Plugin - read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
35-
intellij {
36-
pluginName = properties("pluginName")
37-
version = properties("platformVersion")
38-
type = properties("platformType")
39-
40-
// Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file.
41-
plugins = properties("platformPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) }
49+
jvmToolchain(21)
4250
}
4351

44-
// Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
45-
changelog {
46-
groups.empty()
47-
repositoryUrl = properties("pluginRepositoryUrl")
48-
}
49-
50-
// Configure Gradle Kover Plugin - read more: https://github.com/Kotlin/kotlinx-kover#configuration
51-
koverReport {
52-
defaults {
53-
xml {
54-
onCheck = true
55-
}
56-
}
57-
}
58-
59-
tasks {
60-
wrapper {
61-
gradleVersion = properties("gradleVersion").get()
62-
}
63-
64-
patchPluginXml {
52+
// Configure IntelliJ Platform Gradle Plugin - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-extension.html
53+
intellijPlatform {
54+
pluginConfiguration {
6555
version = properties("pluginVersion")
66-
sinceBuild = properties("pluginSinceBuild")
67-
untilBuild = properties("pluginUntilBuild")
68-
56+
name = properties("pluginName")
57+
6958
// Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest
70-
pluginDescription = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map {
59+
description = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map {
7160
val start = "<!-- Plugin description -->"
7261
val end = "<!-- Plugin description end -->"
73-
62+
7463
with (it.lines()) {
7564
if (!containsAll(listOf(start, end))) {
7665
throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
7766
}
7867
subList(indexOf(start) + 1, indexOf(end)).joinToString("\n").let(::markdownToHTML)
7968
}
8069
}
81-
70+
8271
val changelog = project.changelog // local variable for configuration cache compatibility
8372
// Get the latest available change notes from the changelog file
8473
changeNotes = properties("pluginVersion").map { pluginVersion ->
@@ -91,29 +80,57 @@ tasks {
9180
)
9281
}
9382
}
83+
84+
ideaVersion {
85+
sinceBuild = properties("pluginSinceBuild")
86+
untilBuild = properties("pluginUntilBuild")
87+
}
9488
}
95-
96-
// Configure UI tests plugin
97-
// Read more: https://github.com/JetBrains/intellij-ui-test-robot
98-
runIdeForUiTests {
99-
systemProperty("robot-server.port", "8082")
100-
systemProperty("ide.mac.message.dialogs.as.sheets", "false")
101-
systemProperty("jb.privacy.policy.text", "<!--999.999-->")
102-
systemProperty("jb.consents.confirmation.enabled", "false")
89+
90+
publishing {
91+
token = environment("PUBLISH_TOKEN")
92+
// The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
93+
// Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:
94+
// https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel
95+
channels = properties("pluginVersion").map { listOf(it.substringAfter('-', "").substringBefore('.').ifEmpty { "default" }) }
10396
}
104-
105-
signPlugin {
97+
98+
signing {
10699
certificateChain = environment("CERTIFICATE_CHAIN")
107100
privateKey = environment("PRIVATE_KEY")
108101
password = environment("PRIVATE_KEY_PASSWORD")
109102
}
103+
104+
pluginVerification {
105+
ides {
106+
recommended()
107+
}
108+
}
109+
}
110110

111+
// Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
112+
changelog {
113+
groups.empty()
114+
repositoryUrl = properties("pluginRepositoryUrl")
115+
}
116+
117+
// Configure Gradle Kover Plugin - read more: https://github.com/Kotlin/kotlinx-kover#configuration
118+
kover {
119+
reports {
120+
filters {
121+
excludes {
122+
// Exclude generated code and build files if needed
123+
}
124+
}
125+
}
126+
}
127+
128+
tasks {
129+
wrapper {
130+
gradleVersion = properties("gradleVersion").get()
131+
}
132+
111133
publishPlugin {
112134
dependsOn("patchChangelog")
113-
token = environment("PUBLISH_TOKEN")
114-
// The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
115-
// Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:
116-
// https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel
117-
channels = properties("pluginVersion").map { listOf(it.substringAfter('-', "").substringBefore('.').ifEmpty { "default" }) }
118135
}
119-
}
136+
}

lsp/client/jetbrains/gradle.properties

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
# IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html
22

33
pluginGroup = com.github.mercari.grpcfederation
4-
pluginName = grpc-federation
4+
pluginName = gRPC Federation
55
pluginRepositoryUrl = https://github.com/mercari/grpc-federation
66
# SemVer format -> https://semver.org
7-
pluginVersion = 0.1.0
7+
pluginVersion = 0.2.0
88

99
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
10-
pluginSinceBuild = 233
11-
pluginUntilBuild = 241.*
10+
pluginSinceBuild = 243
11+
# pluginUntilBuild is intentionally not set to allow the plugin to be compatible with future IDE versions.
12+
# This is relatively safe because:
13+
# 1. This plugin uses stable LSP (Language Server Protocol) APIs which are unlikely to break
14+
# 2. The plugin has minimal IDE integration surface area
15+
# 3. Users can install and test on newer versions without waiting for plugin updates
16+
# If compatibility issues arise in future versions, we can add the restriction then.
17+
pluginUntilBuild =
1218

1319
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
1420
platformType = IU
15-
platformVersion = 2023.3.5
21+
platformVersion = 2024.3.3
1622

1723
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
1824
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
1925
platformPlugins =
2026

2127
# Gradle Releases -> https://github.com/gradle/gradle/releases
22-
gradleVersion = 8.6
28+
gradleVersion = 8.10
2329

2430
# Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib
2531
kotlin.stdlib.default.dependency = false

lsp/client/jetbrains/gradle/libs.versions.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33
annotations = "24.1.0"
44

55
# plugins
6-
kotlin = "1.9.23"
7-
changelog = "2.2.0"
8-
gradleIntelliJPlugin = "1.17.2"
9-
qodana = "2023.3.1"
10-
kover = "0.7.6"
6+
kotlin = "2.1.0"
7+
changelog = "2.2.1"
8+
gradleIntelliJPlugin = "2.7.2"
9+
qodana = "2024.2.5"
10+
kover = "0.8.3"
1111

1212
[libraries]
1313
annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" }
1414

1515
[plugins]
1616
changelog = { id = "org.jetbrains.changelog", version.ref = "changelog" }
17-
gradleIntelliJPlugin = { id = "org.jetbrains.intellij", version.ref = "gradleIntelliJPlugin" }
17+
gradleIntelliJPlugin = { id = "org.jetbrains.intellij.platform", version.ref = "gradleIntelliJPlugin" }
1818
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
1919
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
2020
qodana = { id = "org.jetbrains.qodana", version.ref = "qodana" }

0 commit comments

Comments
 (0)