mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[markdown] IJPL-177111 make RPC for Markdown link opening
GitOrigin-RevId: 190ccbebb108dc279f8113551afd164325d4a02b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b33938c543
commit
fbbd8a9b2f
@@ -1,5 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="5" platform="JVM 17" allPlatforms="JVM [17]" useProjectSettings="false">
|
||||
<compilerSettings>
|
||||
<option name="additionalArguments" value="-Xjvm-default=all" />
|
||||
</compilerSettings>
|
||||
<compilerArguments>
|
||||
<stringArguments>
|
||||
<stringArg name="jvmTarget" arg="17" />
|
||||
<stringArg name="apiVersion" arg="2.0" />
|
||||
<stringArg name="languageVersion" arg="2.0" />
|
||||
</stringArguments>
|
||||
<arrayArguments>
|
||||
<arrayArg name="pluginClasspaths">
|
||||
<args>
|
||||
<arg>$KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar</arg>
|
||||
<arg>$MAVEN_REPOSITORY$/jetbrains/fleet/rhizomedb-compiler-plugin/2.1.10-0.1/rhizomedb-compiler-plugin-2.1.10-0.1.jar</arg>
|
||||
<arg>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/2.1.10-0.1/rpc-compiler-plugin-2.1.10-0.1.jar</arg>
|
||||
</args>
|
||||
</arrayArg>
|
||||
<arrayArg name="pluginOptions" />
|
||||
</arrayArguments>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
@@ -16,5 +42,13 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.diagnostic" />
|
||||
<orderEntry type="library" name="jetbrains.markdown" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.backend" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.platform.kernel.backend" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.core" />
|
||||
<orderEntry type="module" module-name="intellij.platform.project" />
|
||||
<orderEntry type="module" module-name="intellij.driver.sdk" />
|
||||
<orderEntry type="module" module-name="intellij.platform.lang" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.core.impl" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,5 +1,10 @@
|
||||
<idea-plugin>
|
||||
<dependencies>
|
||||
<plugin id="com.intellij.platform.experimental.backend"/>
|
||||
<module name="intellij.platform.kernel.backend"/>
|
||||
</dependencies>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<platform.rpc.backend.remoteApiProvider
|
||||
implementation="org.intellij.plugins.markdown.backend.providers.LinkOpenerApiProvider"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package org.intellij.plugins.markdown.backend.providers
|
||||
|
||||
import com.intellij.platform.rpc.backend.RemoteApiProvider
|
||||
import fleet.rpc.remoteApiDescriptor
|
||||
import org.intellij.plugins.markdown.backend.services.MarkdownLinkOpenerRemoteApiImpl
|
||||
import org.intellij.plugins.markdown.service.MarkdownLinkOpenerRemoteApi
|
||||
|
||||
private class LinkOpenerApiProvider : RemoteApiProvider {
|
||||
override fun RemoteApiProvider.Sink.remoteApis() {
|
||||
remoteApi(remoteApiDescriptor<MarkdownLinkOpenerRemoteApi>()) {
|
||||
MarkdownLinkOpenerRemoteApiImpl()
|
||||
}
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors.
|
||||
// Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.intellij.plugins.markdown.backend.services
|
||||
|
||||
import com.intellij.ide.actions.OpenFileAction
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.guessProjectForFile
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.project.ProjectId
|
||||
import com.intellij.platform.project.findProject
|
||||
import com.intellij.platform.project.projectId
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.PsiUtilCore
|
||||
import com.intellij.util.PsiNavigateUtil
|
||||
import com.intellij.util.UriUtil
|
||||
import org.intellij.plugins.markdown.dto.MarkdownHeaderInfo
|
||||
import org.intellij.plugins.markdown.lang.index.HeaderAnchorIndex
|
||||
import org.intellij.plugins.markdown.mapper.MarkdownHeaderMapper
|
||||
import org.intellij.plugins.markdown.service.MarkdownLinkOpenerRemoteApi
|
||||
import org.intellij.plugins.markdown.ui.preview.MarkdownEditorWithPreview
|
||||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
import java.nio.file.Path
|
||||
|
||||
internal class MarkdownLinkOpenerRemoteApiImpl : MarkdownLinkOpenerRemoteApi {
|
||||
companion object {
|
||||
private val logger: Logger = Logger.getInstance(MarkdownLinkOpenerRemoteApiImpl::class.java)
|
||||
}
|
||||
|
||||
override suspend fun openFile(projectId: ProjectId, uri: String) {
|
||||
val project = projectId.findProject()
|
||||
val parsedUri = parseUri(uri)?: return
|
||||
OpenFileAction.openFile(parsedUri.path, project)
|
||||
}
|
||||
|
||||
private fun parseUri(uri: String): URI? {
|
||||
return try {
|
||||
URI(uri)
|
||||
} catch (e: URISyntaxException) {
|
||||
logger.warn(e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun collectHeaders(projectId: ProjectId?, uri: String): List<MarkdownHeaderInfo> {
|
||||
val project = projectId?.findProject() ?: return emptyList()
|
||||
val parsedUri = parseUri(uri)?: return emptyList()
|
||||
val targetFile = parsedUri.findVirtualFile() ?: return emptyList()
|
||||
val anchor = parsedUri.fragment
|
||||
|
||||
return runReadAction {
|
||||
if (DumbService.isDumb(project)) {
|
||||
return@runReadAction emptyList()
|
||||
}
|
||||
val scope = when (val file = PsiManager.getInstance(project).findFile(targetFile)) {
|
||||
null -> GlobalSearchScope.EMPTY_SCOPE
|
||||
else -> GlobalSearchScope.fileScope(file)
|
||||
}
|
||||
return@runReadAction HeaderAnchorIndex.collectHeaders(project, scope, anchor).map(MarkdownHeaderMapper::map)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun guessProjectForUri(uri: String): ProjectId? {
|
||||
val parsedUri = parseUri(uri) ?: return null
|
||||
val file = parsedUri.findVirtualFile() ?: return null
|
||||
val project = guessProjectForFile(file) ?: return null
|
||||
return project.projectId()
|
||||
}
|
||||
|
||||
override suspend fun navigateToHeader(projectId: ProjectId, headerInfo: MarkdownHeaderInfo) {
|
||||
val uri = createFileUri(headerInfo.filePath) ?: return
|
||||
val file = uri.findVirtualFile() ?: return
|
||||
val project = projectId.findProject()
|
||||
val manager = FileEditorManager.getInstance(project)
|
||||
val openedEditors = manager.getEditorList(file).filterIsInstance<MarkdownEditorWithPreview>()
|
||||
val psiFile = PsiUtilCore.getPsiFile(project, file)
|
||||
val element = psiFile.findElementAt(headerInfo.textOffset) ?: return
|
||||
if (openedEditors.isNotEmpty()) {
|
||||
openedEditors.forEach {
|
||||
// Ensures the element is located as in the original implementation
|
||||
PsiUtilCore.getElementAtOffset(psiFile, element.textOffset)
|
||||
PsiNavigateUtil.navigate(element, true)
|
||||
}
|
||||
return
|
||||
}
|
||||
val descriptor = OpenFileDescriptor(project, file, element.textOffset)
|
||||
manager.openEditor(descriptor, true)
|
||||
}
|
||||
|
||||
private fun URI.findVirtualFile(): VirtualFile? {
|
||||
val actualPath = when {
|
||||
SystemInfo.isWindows -> UriUtil.trimLeadingSlashes(path)
|
||||
else -> path
|
||||
}
|
||||
val path = Path.of(actualPath)
|
||||
return VfsUtil.findFile(path, true)
|
||||
}
|
||||
|
||||
private fun createFileUri(link: String): URI? {
|
||||
return try {
|
||||
URI("file", null, link, null)
|
||||
} catch (e: URISyntaxException) {
|
||||
logger.warn(e)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="5" platform="JVM 17" allPlatforms="JVM [17]" useProjectSettings="false">
|
||||
<compilerSettings>
|
||||
<option name="additionalArguments" value="-Xjvm-default=all" />
|
||||
</compilerSettings>
|
||||
<compilerArguments>
|
||||
<stringArguments>
|
||||
<stringArg name="jvmTarget" arg="17" />
|
||||
<stringArg name="apiVersion" arg="2.0" />
|
||||
<stringArg name="languageVersion" arg="2.0" />
|
||||
</stringArguments>
|
||||
<arrayArguments>
|
||||
<arrayArg name="pluginClasspaths">
|
||||
<args>
|
||||
<arg>$KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar</arg>
|
||||
<arg>$MAVEN_REPOSITORY$/jetbrains/fleet/rhizomedb-compiler-plugin/2.1.10-0.1/rhizomedb-compiler-plugin-2.1.10-0.1.jar</arg>
|
||||
<arg>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/2.1.10-0.1/rpc-compiler-plugin-2.1.10-0.1.jar</arg>
|
||||
</args>
|
||||
</arrayArg>
|
||||
<arrayArg name="pluginOptions" />
|
||||
</arrayArguments>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
@@ -15,5 +41,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.util.netty" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.ui" />
|
||||
<orderEntry type="module" module-name="intellij.platform.kernel" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,5 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="5" platform="JVM 17" allPlatforms="JVM [17]" useProjectSettings="false">
|
||||
<compilerSettings>
|
||||
<option name="additionalArguments" value="-Xjvm-default=all" />
|
||||
</compilerSettings>
|
||||
<compilerArguments>
|
||||
<stringArguments>
|
||||
<stringArg name="jvmTarget" arg="17" />
|
||||
<stringArg name="apiVersion" arg="2.0" />
|
||||
<stringArg name="languageVersion" arg="2.0" />
|
||||
</stringArguments>
|
||||
<arrayArguments>
|
||||
<arrayArg name="pluginClasspaths">
|
||||
<args>
|
||||
<arg>$KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar</arg>
|
||||
<arg>$MAVEN_REPOSITORY$/jetbrains/fleet/rhizomedb-compiler-plugin/2.1.10-0.1/rhizomedb-compiler-plugin-2.1.10-0.1.jar</arg>
|
||||
<arg>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/2.1.10-0.1/rpc-compiler-plugin-2.1.10-0.1.jar</arg>
|
||||
</args>
|
||||
</arrayArg>
|
||||
<arrayArg name="pluginOptions" />
|
||||
</arrayArguments>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
@@ -47,5 +73,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.project" />
|
||||
<orderEntry type="library" name="kotlinx-serialization-core" level="project" />
|
||||
<orderEntry type="library" name="kotlinx-serialization-json" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.kernel" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.intellij.plugins.markdown.service
|
||||
|
||||
import com.intellij.platform.project.ProjectId
|
||||
import com.intellij.platform.rpc.RemoteApiProviderService
|
||||
import fleet.rpc.RemoteApi
|
||||
import fleet.rpc.Rpc
|
||||
import fleet.rpc.remoteApiDescriptor
|
||||
import org.intellij.plugins.markdown.dto.MarkdownHeaderInfo
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Rpc
|
||||
interface MarkdownLinkOpenerRemoteApi: RemoteApi<Unit> {
|
||||
suspend fun openFile(projectId: ProjectId, uri: String)
|
||||
suspend fun collectHeaders(projectId: ProjectId?, uri: String): List<MarkdownHeaderInfo>
|
||||
suspend fun guessProjectForUri(uri: String): ProjectId?
|
||||
suspend fun navigateToHeader(projectId: ProjectId, headerInfo: MarkdownHeaderInfo)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
suspend fun getInstance(): MarkdownLinkOpenerRemoteApi {
|
||||
return RemoteApiProviderService.resolve(remoteApiDescriptor<MarkdownLinkOpenerRemoteApi>())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user