mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
[javadoc] Add a cache for javadoc fragment ids
#IDEA-376337 GitOrigin-RevId: 5eefe6cfb1ba5e04fe8cba24592ca7ea1d6c9a9c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cf0b1ecfab
commit
1a9c32c51b
+67
@@ -0,0 +1,67 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.javadoc.index
|
||||
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.javadoc.PsiDocComment
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.util.indexing.ID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@JvmField
|
||||
val NAME: ID<String, LinkedHashSet<JavaDocFragmentData>> = ID.create("java.javadoc.fragment.anchors")
|
||||
|
||||
data class JavaDocFragmentData(val name: String, val offset: Int)
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
private class JavaDocFragmentCacheService {
|
||||
private data class Entry(val stamp: Long, val data: LinkedHashSet<JavaDocFragmentData>)
|
||||
private val cache: ConcurrentHashMap<String, Entry> = ConcurrentHashMap()
|
||||
|
||||
// Matches any HTML opening tag with an id attribute
|
||||
private val ID_PATTERN: Pattern = Pattern.compile("<[a-zA-Z0-9\\-]*[^>] id=[\"']?([^\"'> ]+)[\"']?[^>]*>", Pattern.CASE_INSENSITIVE)
|
||||
|
||||
fun getAnchors(project: Project, fqn: String): LinkedHashSet<JavaDocFragmentData> {
|
||||
val entry = cache[fqn]
|
||||
val psiClass = JavaPsiFacade.getInstance(project).findClass(fqn, GlobalSearchScope.projectScope(project))
|
||||
val file = psiClass?.containingFile ?: return LinkedHashSet()
|
||||
if (entry != null && file.modificationStamp == entry.stamp) return entry.data
|
||||
|
||||
val result = LinkedHashSet<JavaDocFragmentData>().apply {
|
||||
addAll(findIdsFromComment(psiClass.docComment))
|
||||
for (method in psiClass.methods) addAll(findIdsFromComment(method.docComment))
|
||||
for (field in psiClass.fields) addAll(findIdsFromComment(field.docComment))
|
||||
}
|
||||
|
||||
cache[fqn] = Entry(file.modificationStamp, result)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findIdsFromComment(docComment: PsiDocComment?): List<JavaDocFragmentData> {
|
||||
val text = docComment?.text ?: return listOf()
|
||||
if (" id=" !in text && " ID=" !in text) return listOf()
|
||||
val offset = docComment.textOffset
|
||||
return findIdsFromText(text)
|
||||
.map { JavaDocFragmentData(it.name, it.offset + offset) }
|
||||
}
|
||||
|
||||
private fun findIdsFromText(docText: String): List<JavaDocFragmentData> {
|
||||
return ID_PATTERN.matcher(docText).results()
|
||||
.map { result ->
|
||||
val id = result.group(1)
|
||||
when (id != null && !id.isBlank()) {
|
||||
true -> JavaDocFragmentData(id, result.start(1))
|
||||
false -> null
|
||||
}
|
||||
}
|
||||
.toList()
|
||||
.filterNotNull()
|
||||
}
|
||||
}
|
||||
|
||||
fun getAnchors(project: Project, fqnOrPackage: String): LinkedHashSet<JavaDocFragmentData> {
|
||||
return project.service<JavaDocFragmentCacheService>().getAnchors(project, fqnOrPackage)
|
||||
}
|
||||
Reference in New Issue
Block a user