mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[gradle][IDEA-378369] remove 'Download Sources' button from the quick doc popup
GitOrigin-RevId: 13b60ddecbab86878acff576e59a3145b5670279
This commit is contained in:
committed by
intellij-monorepo-bot
parent
69e6d960c6
commit
feca4c4016
@@ -18,7 +18,6 @@ public interface DocumentationMarkup {
|
||||
@ApiStatus.Internal String CLASS_CENTERED = "centered";
|
||||
@ApiStatus.Internal String CLASS_BOTTOM = "bottom";
|
||||
@ApiStatus.Internal String CLASS_TOP = "top";
|
||||
@ApiStatus.Internal String CLASS_DOWNLOAD_DOCUMENTATION = "download-documentation";
|
||||
|
||||
@NlsSafe String DEFINITION_START = "<div class='" + CLASS_DEFINITION + "'><pre>";
|
||||
@NlsSafe String DEFINITION_END = "</pre></div>";
|
||||
|
||||
@@ -576,7 +576,6 @@ tooltip.computing.classes.for.auto.import=Computing classes to auto-import\u2026
|
||||
jvm.inspections.dependency.configure.button.text=Configure dependency rules
|
||||
checking.code.highlightings.in.background=Loading Code Highlighting
|
||||
title.checking.code.highlightings.in.background.task=Loading code passes
|
||||
documentation.download.button.label=Download documentation
|
||||
command.completion.title=Commands
|
||||
command.completion.filter.hint=press ''{0}'' to show commands
|
||||
command.completion.project.tool.text=Project tool
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ object DocumentationHtmlUtil {
|
||||
padding: 0 ${contentInnerPadding}px 0px ${contentInnerPadding}px;
|
||||
max-width: 100%;
|
||||
}
|
||||
.$CLASS_BOTTOM, .$CLASS_DOWNLOAD_DOCUMENTATION, .$CLASS_TOP {
|
||||
.$CLASS_BOTTOM, .$CLASS_TOP {
|
||||
padding: ${beforeSpacing}px ${contentInnerPadding}px ${afterSpacing}px ${contentInnerPadding}px;
|
||||
}
|
||||
.$CLASS_SECTIONS { padding: 0 ${contentInnerPadding - 2}px 0 ${contentInnerPadding - 2}px 0; border-spacing: 0; }
|
||||
|
||||
+2
-17
@@ -83,7 +83,6 @@ import org.jetbrains.annotations.*;
|
||||
import org.jetbrains.concurrency.CancellablePromise;
|
||||
import org.jetbrains.concurrency.Promises;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.nodes.TextNode;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -1821,7 +1820,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
@Nullable DocumentationProvider provider
|
||||
) {
|
||||
HtmlChunk locationInfo = getDefaultLocationInfo(element);
|
||||
return decorate(text, locationInfo, getExternalText(element, externalUrl, provider), null);
|
||||
return decorate(text, locationInfo, getExternalText(element, externalUrl, provider));
|
||||
}
|
||||
|
||||
@RequiresReadLock
|
||||
@@ -1861,8 +1860,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
|
||||
@Internal
|
||||
@Contract(pure = true)
|
||||
public static @Nls String decorate(@Nls @NotNull String text, @Nullable HtmlChunk location, @Nullable HtmlChunk links,
|
||||
@Nullable String downloadDocumentationActionLink) {
|
||||
public static @Nls String decorate(@Nls @NotNull String text, @Nullable HtmlChunk location, @Nullable HtmlChunk links) {
|
||||
text = StringUtil.replaceIgnoreCase(text, "</html>", "");
|
||||
text = StringUtil.replaceIgnoreCase(text, "</body>", "");
|
||||
|
||||
@@ -1883,18 +1881,6 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
|
||||
DocumentationHtmlUtil.removeEmptySections$intellij_platform_lang_impl(document);
|
||||
|
||||
if (downloadDocumentationActionLink != null) {
|
||||
document.body().appendChild(
|
||||
new Element("div")
|
||||
.addClass(CLASS_DOWNLOAD_DOCUMENTATION)
|
||||
.appendChildren(Arrays.asList(
|
||||
new Element("icon").attr("src", "AllIcons.Plugins.Downloads"),
|
||||
new TextNode(" "),
|
||||
new Element("a").attr("href", downloadDocumentationActionLink)
|
||||
.text(CodeInsightBundle.message("documentation.download.button.label"))
|
||||
)));
|
||||
}
|
||||
if (location != null) {
|
||||
document.body().append(getBottom().child(location).toString());
|
||||
}
|
||||
@@ -1914,7 +1900,6 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
&& (
|
||||
nextSibling.hasClass(CLASS_SECTIONS)
|
||||
|| nextSibling.hasClass(CLASS_BOTTOM)
|
||||
|| nextSibling.hasClass(CLASS_DOWNLOAD_DOCUMENTATION)
|
||||
))) {
|
||||
div.after(new Element("hr"));
|
||||
}
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.documentation.actions
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Experimental
|
||||
interface DocumentationDownloader {
|
||||
|
||||
suspend fun canHandle(project: Project, file: VirtualFile): Boolean
|
||||
|
||||
suspend fun download(project: Project, file: VirtualFile): Boolean
|
||||
|
||||
companion object {
|
||||
val EP = ExtensionPointName.create<DocumentationDownloader>("com.intellij.documentation.documentationDownloader")
|
||||
const val HREF_PREFIX = "download_sources:"
|
||||
|
||||
fun formatLink(target: VirtualFile?): String? {
|
||||
val virtualFileUrl: String = target?.url ?: return null
|
||||
return HREF_PREFIX + virtualFileUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
-35
@@ -1,21 +1,16 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.lang.documentation.ide.impl
|
||||
|
||||
import com.intellij.codeInsight.documentation.actions.DocumentationDownloader
|
||||
import com.intellij.codeInsight.lookup.LookupManager
|
||||
import com.intellij.lang.documentation.ide.impl.DocumentationUsageCollector.logDownloadFinished
|
||||
import com.intellij.lang.documentation.ide.ui.DocumentationUI
|
||||
import com.intellij.lang.documentation.ide.ui.UISnapshot
|
||||
import com.intellij.model.Pointer
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.IndexNotReadyException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.OrderEntry
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.platform.backend.documentation.DocumentationTarget
|
||||
import com.intellij.platform.backend.documentation.impl.DocumentationRequest
|
||||
import com.intellij.platform.backend.documentation.impl.InternalLinkResult
|
||||
@@ -120,11 +115,6 @@ internal class DocumentationBrowser private constructor(
|
||||
}
|
||||
|
||||
private suspend fun handleLinkRequest(url: String) {
|
||||
if (url.startsWith(DocumentationDownloader.HREF_PREFIX)) {
|
||||
handleDownloadSourcesRequest(url)
|
||||
return
|
||||
}
|
||||
|
||||
val targetPointer = this.targetPointer
|
||||
val internalResult = try {
|
||||
handleLink(project, targetPointer, url, page)
|
||||
@@ -159,22 +149,6 @@ internal class DocumentationBrowser private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDownloadSourcesRequest(href: String) {
|
||||
val filePath = href.replaceFirst(DocumentationDownloader.HREF_PREFIX, "")
|
||||
val file = VirtualFileManager.getInstance().findFileByUrl(filePath)
|
||||
if (file != null) {
|
||||
CoroutineScopeService.getCoroutineScope(project)
|
||||
.launch {
|
||||
val handler = DocumentationDownloader.EP.extensionList.find { it.canHandle(project, file) }
|
||||
if (handler != null) {
|
||||
val success = handler.download(project, file)
|
||||
logDownloadFinished(project, handler::class.java, success)
|
||||
}
|
||||
}
|
||||
closeTrigger?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleRestoreRequest(snapshot: HistorySnapshot) {
|
||||
val page = snapshot.page
|
||||
val restored = page.restorePage(snapshot.ui)
|
||||
@@ -220,13 +194,4 @@ internal class DocumentationBrowser private constructor(
|
||||
*/
|
||||
suspend fun DocumentationBrowser.waitForContent(): Boolean = pageFlow.first().waitForContent()
|
||||
}
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
private class CoroutineScopeService(val coroutineScope: CoroutineScope) {
|
||||
companion object {
|
||||
fun getCoroutineScope(project: Project): CoroutineScope {
|
||||
return project.service<CoroutineScopeService>().coroutineScope
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-20
@@ -3,21 +3,17 @@
|
||||
|
||||
package com.intellij.lang.documentation.ide.impl
|
||||
|
||||
import com.intellij.codeInsight.documentation.actions.DocumentationDownloader
|
||||
import com.intellij.lang.documentation.ide.ui.ExpandableDefinition
|
||||
import com.intellij.lang.documentation.ide.ui.UISnapshot
|
||||
import com.intellij.lang.documentation.ide.ui.UIState
|
||||
import com.intellij.lang.documentation.ide.ui.createExpandableDefinition
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.project.IndexNotReadyException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.backend.documentation.ContentUpdater
|
||||
import com.intellij.platform.backend.documentation.DocumentationContentData
|
||||
import com.intellij.platform.backend.documentation.LinkData
|
||||
import com.intellij.platform.backend.documentation.impl.DocumentationRequest
|
||||
import com.intellij.platform.backend.documentation.impl.computeDocumentation
|
||||
import com.intellij.psi.PsiElement
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
@@ -68,17 +64,8 @@ internal class DocumentationPage(val requests: List<DocumentationRequest>, val p
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun prepareContent(content: DocumentationContentData, links: LinkData, uiState: UIState?): DocumentationPageContent.Content {
|
||||
var downloadSourcesLink: String? = null
|
||||
if (content.targetElement != null) {
|
||||
val targetFile = readAction { content.targetElement.getTargetFile() }
|
||||
if (targetFile != null) {
|
||||
if (DocumentationDownloader.EP.extensionList.find { it.canHandle(project, targetFile) } != null) {
|
||||
downloadSourcesLink = DocumentationDownloader.formatLink(targetFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
return DocumentationPageContent.Content(content, links, uiState, downloadSourcesLink)
|
||||
private fun prepareContent(content: DocumentationContentData, links: LinkData, uiState: UIState?): DocumentationPageContent.Content {
|
||||
return DocumentationPageContent.Content(content, links, uiState)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,10 +102,6 @@ internal class DocumentationPage(val requests: List<DocumentationRequest>, val p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement.getTargetFile(): VirtualFile? = containingFile?.run {
|
||||
virtualFile ?: originalFile.virtualFile
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class DocumentationPageContent {
|
||||
@@ -129,6 +112,5 @@ internal sealed class DocumentationPageContent {
|
||||
val content: DocumentationContentData,
|
||||
val links: LinkData,
|
||||
val uiState: UIState?,
|
||||
val downloadSourcesLink: String?
|
||||
) : DocumentationPageContent()
|
||||
}
|
||||
|
||||
+1
-12
@@ -1,24 +1,17 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.lang.documentation.ide.impl
|
||||
|
||||
import com.intellij.codeInsight.documentation.actions.DocumentationDownloader
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||
import com.intellij.internal.statistic.eventLog.events.EventId2
|
||||
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
|
||||
import com.intellij.lang.documentation.psi.PsiElementDocumentationTarget
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.backend.documentation.DocumentationTarget
|
||||
|
||||
object DocumentationUsageCollector : CounterUsagesCollector() {
|
||||
override fun getGroup(): EventLogGroup = GROUP
|
||||
|
||||
private val GROUP = EventLogGroup("documentation", 5)
|
||||
|
||||
private val DOWNLOAD_FINISHED_EVENT = GROUP.registerEvent("quick.doc.download.finished",
|
||||
EventFields.Class("handler"),
|
||||
EventFields.Boolean("success")
|
||||
)
|
||||
private val GROUP = EventLogGroup("documentation", 6)
|
||||
|
||||
val QUICK_DOC_SHOWN = GROUP.registerEvent("quick.doc.shown", EventFields.FileType)
|
||||
val QUICK_DOC_CLOSED = GROUP.registerEvent("quick.doc.closed", EventFields.FileType, EventFields.Boolean("joint"), EventFields.DurationMs)
|
||||
@@ -32,10 +25,6 @@ object DocumentationUsageCollector : CounterUsagesCollector() {
|
||||
EventFields.Enum("protocol", DocumentationLinkProtocol::class.java),
|
||||
EventFields.Boolean("lookup_active"),
|
||||
)
|
||||
|
||||
fun logDownloadFinished(project: Project, handlerClass: Class<out DocumentationDownloader>, success: Boolean) {
|
||||
DOWNLOAD_FINISHED_EVENT.log(project, handlerClass, success)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getClassRefForStatistics(dereference: DocumentationTarget?): Class<out Any>? {
|
||||
|
||||
@@ -293,7 +293,7 @@ internal class DocumentationUI(
|
||||
imageResolver = content.imageResolver
|
||||
val linkChunk = linkChunk(presentation.presentableText, pageContent.links)
|
||||
val decoratedData = extractAdditionalData(content.html)
|
||||
val decorated = decorate(decoratedData?.html ?: content.html, null, linkChunk, pageContent.downloadSourcesLink)
|
||||
val decorated = decorate(decoratedData?.html ?: content.html, null, linkChunk)
|
||||
if (!updateContent(decorated, presentation, ContentKind.DocumentationPage, decoratedData?.decoratedStyle)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -601,8 +601,6 @@
|
||||
<extensionPoint name="elementPreviewProvider" interface="com.intellij.codeInsight.preview.ElementPreviewProvider" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="testActionProvider" interface="com.intellij.execution.testframework.ToggleModelActionProvider" dynamic="true"/>
|
||||
<extensionPoint name="documentation.documentationDownloader"
|
||||
interface="com.intellij.codeInsight.documentation.actions.DocumentationDownloader" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="testDiffProvider" beanClass="com.intellij.lang.LanguageExtensionPoint" dynamic="true">
|
||||
<with attribute="implementationClass" implements="com.intellij.execution.testframework.actions.TestDiffProvider"/>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.plugins.gradle.codeInsight.documentation
|
||||
|
||||
import com.intellij.codeEditor.JavaEditorFileSwapper
|
||||
import com.intellij.codeInsight.documentation.actions.DocumentationDownloader
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.plugins.gradle.service.sources.GradleLibrarySourcesDownloader
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
||||
|
||||
class GradleDocumentationDownloader : DocumentationDownloader {
|
||||
|
||||
override suspend fun canHandle(project: Project, file: VirtualFile): Boolean {
|
||||
if (!FileTypeRegistry.getInstance().isFileOfType(file, JavaClassFileType.INSTANCE)) {
|
||||
return false
|
||||
}
|
||||
if (GradleSettings.getInstance(project).linkedProjectsSettings.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
if (!GradleLibrarySourcesDownloader.canDownloadSources(project, file)) {
|
||||
return false
|
||||
}
|
||||
return readAction { JavaEditorFileSwapper.findSourceFile(project, file) == null }
|
||||
}
|
||||
|
||||
override suspend fun download(project: Project, file: VirtualFile): Boolean {
|
||||
return GradleLibrarySourcesDownloader.download(project, file) != null
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.plugins.gradle.service.sources
|
||||
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.jarFinder.InternetAttachSourceProvider.attachSourceJar
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.externalSystem.model.project.LibraryPathType
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry
|
||||
import com.intellij.openapi.roots.OrderRootType
|
||||
import com.intellij.openapi.roots.ProjectFileIndex
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.future.await
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.plugins.gradle.execution.build.CachedModuleDataFinder
|
||||
import org.jetbrains.plugins.gradle.execution.target.maybeGetLocalValue
|
||||
import org.jetbrains.plugins.gradle.service.GradleInstallationManager
|
||||
import org.jetbrains.plugins.gradle.service.cache.GradleLocalCacheHelper
|
||||
import org.jetbrains.plugins.gradle.util.*
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
|
||||
object GradleLibrarySourcesDownloader {
|
||||
|
||||
suspend fun canDownloadSources(project: Project, file: VirtualFile): Boolean {
|
||||
if (!file.isClassFile()) {
|
||||
return false
|
||||
}
|
||||
val entries = findLibraryEntriesForFile(project, file)
|
||||
if (entries.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
return canDownloadSources(entries)
|
||||
}
|
||||
|
||||
fun canDownloadSources(orderEntries: List<LibraryOrderEntry>): Boolean {
|
||||
return findAssociatedGradleModule(orderEntries) != null
|
||||
}
|
||||
|
||||
suspend fun download(project: Project, file: VirtualFile): Path? =
|
||||
download(project, file, DefaultGradleDependencySourceDownloaderErrorHandler)
|
||||
|
||||
suspend fun download(project: Project, file: VirtualFile, errorHandler: GradleDependencySourceDownloaderErrorHandler): Path? {
|
||||
if (!file.isClassFile()) {
|
||||
return null
|
||||
}
|
||||
val libraryEntries = findLibraryEntriesForFile(project, file)
|
||||
return download(project, libraryEntries, errorHandler)
|
||||
}
|
||||
|
||||
suspend fun download(project: Project, orderEntries: List<LibraryOrderEntry>): Path? =
|
||||
download(project, orderEntries, DefaultGradleDependencySourceDownloaderErrorHandler)
|
||||
|
||||
suspend fun download(
|
||||
project: Project,
|
||||
orderEntries: List<LibraryOrderEntry>,
|
||||
errorHandler: GradleDependencySourceDownloaderErrorHandler,
|
||||
): Path? {
|
||||
if (orderEntries.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
val module = findAssociatedGradleModule(orderEntries) ?: return null
|
||||
val gradleModuleData = CachedModuleDataFinder.getGradleModuleData(module) ?: return null
|
||||
val externalProjectPath = gradleModuleData.moduleData.linkedExternalProjectPath ?: return null
|
||||
val libraryOrderEntry = orderEntries.first()
|
||||
val sourceArtifactNotation = libraryOrderEntry.getArtifactCoordinates()?.let { "$it:sources" } ?: return null
|
||||
val cachedSourcesPath = lookupSourcesPathFromCache(libraryOrderEntry, sourceArtifactNotation, project, externalProjectPath)
|
||||
if (cachedSourcesPath != null && isValidJar(cachedSourcesPath)) {
|
||||
attachSources(cachedSourcesPath, orderEntries)
|
||||
return cachedSourcesPath
|
||||
}
|
||||
val path = GradleArtifactDownloader.downloadArtifact(
|
||||
project,
|
||||
GradleBundle.message("gradle.action.download.sources"),
|
||||
sourceArtifactNotation,
|
||||
externalProjectPath,
|
||||
errorHandler
|
||||
).await()
|
||||
if (path != null) {
|
||||
attachSources(path, orderEntries)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
private suspend fun attachSources(sourcesJar: Path, orderEntries: List<LibraryOrderEntry>) {
|
||||
withContext(Dispatchers.EDT) {
|
||||
val libraries = HashSet<Library>()
|
||||
orderEntries.forEach {
|
||||
ContainerUtil.addIfNotNull(libraries, it.library)
|
||||
}
|
||||
attachSourceJar(sourcesJar, libraries)
|
||||
}
|
||||
}
|
||||
|
||||
private fun lookupSourcesPathFromCache(
|
||||
libraryOrderEntry: LibraryOrderEntry,
|
||||
sourceArtifactNotation: String,
|
||||
project: Project,
|
||||
projectPath: String,
|
||||
): Path? {
|
||||
val rootFiles = libraryOrderEntry.getRootFiles(OrderRootType.CLASSES)
|
||||
if (rootFiles.size == 0) {
|
||||
return null
|
||||
}
|
||||
val buildLayoutParameters = GradleInstallationManager.getInstance().guessBuildLayoutParameters(project, projectPath)
|
||||
val gradleUserHome = buildLayoutParameters.gradleUserHomePath.maybeGetLocalValue()
|
||||
if (gradleUserHome == null) {
|
||||
return null
|
||||
}
|
||||
val filePath = Path.of(rootFiles[0].path)
|
||||
if (!filePath.startsWith(gradleUserHome)) {
|
||||
return null
|
||||
}
|
||||
val coordinates = getLibraryUnifiedCoordinates(sourceArtifactNotation)
|
||||
if (coordinates == null) {
|
||||
return null
|
||||
}
|
||||
val localArtifacts = GradleLocalCacheHelper.findArtifactComponents(
|
||||
coordinates,
|
||||
gradleUserHome,
|
||||
EnumSet.of(LibraryPathType.SOURCE)
|
||||
)
|
||||
return localArtifacts[LibraryPathType.SOURCE]?.firstOrNull()
|
||||
}
|
||||
|
||||
private fun findAssociatedGradleModule(libraryOrderEntries: List<LibraryOrderEntry>): Module? {
|
||||
return libraryOrderEntries
|
||||
.filter { !it.isModuleLevel }
|
||||
.map { it.ownerModule }
|
||||
.find { ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, it) }
|
||||
}
|
||||
|
||||
private fun VirtualFile.isClassFile(): Boolean {
|
||||
val registry = FileTypeRegistry.getInstance()
|
||||
return registry.isFileOfType(this, JavaClassFileType.INSTANCE)
|
||||
}
|
||||
|
||||
private suspend fun findLibraryEntriesForFile(project: Project, file: VirtualFile): List<LibraryOrderEntry> {
|
||||
return readAction {
|
||||
val index = ProjectFileIndex.getInstance(project)
|
||||
return@readAction index.getOrderEntriesForFile(file)
|
||||
.filterIsInstance<LibraryOrderEntry>()
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:JvmName("ArtifactCoordinatesUtil")
|
||||
|
||||
package org.jetbrains.plugins.gradle.service.sources
|
||||
|
||||
import com.intellij.buildsystem.model.unified.UnifiedCoordinates
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry
|
||||
import com.intellij.openapi.roots.OrderRootType
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import java.util.function.Predicate
|
||||
|
||||
private const val ANDROID_LIBRARY_SUFFIX = "@aar"
|
||||
|
||||
fun LibraryOrderEntry.getArtifactCoordinates(): String? {
|
||||
val libraryName = getLibraryName() ?: return null
|
||||
val artifactCoordinates = libraryName.removePrefix("${GradleConstants.SYSTEM_ID.readableName}: ")
|
||||
if (libraryName == artifactCoordinates) {
|
||||
return null
|
||||
}
|
||||
return parseArtifactCoordinates(artifactCoordinates) { idCandidate ->
|
||||
isArtifactId(idCandidate, this@getArtifactCoordinates)
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun parseArtifactCoordinates(artifactCoordinates: String, artifactIdChecker: Predicate<String>): String {
|
||||
val rawCoordinates = artifactCoordinates.split(":").let {
|
||||
when {
|
||||
it.size == 4 && artifactIdChecker.test(it[1]) -> it[0] + ":" + it[1] + ":" + it[3]
|
||||
it.size == 5 -> it[0] + ":" + it[1] + ":" + it[4]
|
||||
else -> artifactCoordinates
|
||||
}
|
||||
}
|
||||
return rawCoordinates.removeSuffix(ANDROID_LIBRARY_SUFFIX)
|
||||
}
|
||||
|
||||
fun getLibraryUnifiedCoordinates(sourceArtifactNotation: String): UnifiedCoordinates? =
|
||||
sourceArtifactNotation.replace(ANDROID_LIBRARY_SUFFIX, "")
|
||||
.split(":")
|
||||
.let { if (it.size < 3) null else UnifiedCoordinates(it[0], it[1], it[2]) }
|
||||
|
||||
private fun isArtifactId(artifactIdCandidate: String, libraryOrderEntry: LibraryOrderEntry): Boolean {
|
||||
val rootFiles = libraryOrderEntry.getRootFiles(OrderRootType.CLASSES)
|
||||
return rootFiles.size == 0 || rootFiles.any { file -> file.getName().startsWith(artifactIdCandidate) }
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.plugins.gradle.service.sources
|
||||
|
||||
import junit.framework.AssertionFailedError
|
||||
import org.jetbrains.plugins.gradle.DefaultExternalDependencyId
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.util.*
|
||||
|
||||
class ArtifactCoordinatesUtilTest {
|
||||
|
||||
@Test
|
||||
fun `test artifact notation parsing`() {
|
||||
val dependencyId = getRandomDependencyId()
|
||||
val actual = parseArtifactCoordinates(dependencyId.presentableName) { true }
|
||||
assertEquals("${dependencyId.group}:${dependencyId.name}:${dependencyId.version}", actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test artifact notation parsing with classifier`() {
|
||||
val dependencyId = getRandomDependencyId()
|
||||
val classifier = getRandomString()
|
||||
dependencyId.classifier = classifier
|
||||
|
||||
val actual = parseArtifactCoordinates(dependencyId.presentableName) { true }
|
||||
assertEquals("${dependencyId.group}:${dependencyId.name}:${dependencyId.version}", actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test artifact notation parsing with packaging`() {
|
||||
val dependencyId = getRandomDependencyId()
|
||||
val packaging = getRandomString()
|
||||
dependencyId.packaging = packaging
|
||||
|
||||
val actual = parseArtifactCoordinates(dependencyId.presentableName) { true }
|
||||
assertEquals("${dependencyId.group}:${dependencyId.name}:${dependencyId.version}", actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test artifact notation without version`() {
|
||||
val group = getRandomString()
|
||||
val artifact = getRandomString()
|
||||
|
||||
val actual = parseArtifactCoordinates("$group:$artifact") {
|
||||
throw AssertionFailedError("artifactIdChecker shouldn't be called")
|
||||
}
|
||||
assertEquals("$group:$artifact", actual)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `test aar artifact notation parsing`() {
|
||||
val group = getRandomString()
|
||||
val artifact = getRandomString()
|
||||
val version = getRandomString()
|
||||
|
||||
val actual = parseArtifactCoordinates("$group:$artifact:$version@aar") {
|
||||
throw AssertionFailedError("artifactIdChecker shouldn't be called")
|
||||
}
|
||||
assertEquals("$group:$artifact:$version", actual)
|
||||
}
|
||||
|
||||
private fun getRandomString(): String {
|
||||
return UUID.randomUUID().toString().substring(0, 12)
|
||||
}
|
||||
|
||||
private fun getRandomDependencyId(): DefaultExternalDependencyId {
|
||||
return DefaultExternalDependencyId(
|
||||
getRandomString(),
|
||||
getRandomString(),
|
||||
getRandomString()
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user