-
-
Notifications
You must be signed in to change notification settings - Fork 793
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
164 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
...ain/kotlin/cn/yiiguxing/plugin/translate/provider/AbstractDocumentationElementProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package cn.yiiguxing.plugin.translate.provider | ||
|
||
import cn.yiiguxing.plugin.translate.util.startOffset | ||
import com.intellij.openapi.util.Key | ||
import com.intellij.psi.PsiComment | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.PsiFile | ||
import com.intellij.psi.PsiWhiteSpace | ||
import com.intellij.psi.util.PsiTreeUtil | ||
|
||
abstract class AbstractDocumentationElementProvider<T : PsiComment> : DocumentationElementProvider { | ||
|
||
@Suppress("UNCHECKED_CAST") | ||
override fun findDocumentationElementAt(psiFile: PsiFile, offset: Int): T? { | ||
val offsetElement = psiFile.findElementAt(offset) ?: return null | ||
val comment = PsiTreeUtil.getParentOfType(offsetElement, PsiComment::class.java, false) | ||
val documentationElement: T? = if ( | ||
comment == null // 如果当前元素或其父元素是注释元素,则跳过边缘拾取 | ||
&& offsetElement is PsiWhiteSpace | ||
&& offsetElement.startOffset == offset // 光标处于边缘处 | ||
) { | ||
// 如果可在边缘拾取,则从末尾边缘处拾取 | ||
(offsetElement.prevSibling as? T)?.takeIf { it.isPickAtEdge } | ||
} else { | ||
comment as? T | ||
} | ||
|
||
return documentationElement?.takeIf { it.isDocComment && it.cachedOwner.owner != null } | ||
} | ||
|
||
/** | ||
* 检测目标注释是否是文档注释 | ||
*/ | ||
protected abstract val T.isDocComment: Boolean | ||
|
||
/** | ||
* 目标注释是否可在边缘处拾取 | ||
*/ | ||
protected open val T.isPickAtEdge: Boolean get() = false | ||
|
||
final override fun getDocumentationOwner(documentationElement: PsiElement): PsiElement? { | ||
@Suppress("UNCHECKED_CAST") | ||
return (documentationElement as? T)?.cachedOwner?.owner | ||
} | ||
|
||
/** | ||
* 缓存的注释所有者 | ||
*/ | ||
@Suppress("MemberVisibilityCanBePrivate") | ||
protected val T.cachedOwner: CachedOwner | ||
get() { | ||
val modificationStamp = containingFile.modificationStamp | ||
return DOCUMENTATION_OWNER_CACHE[this@cachedOwner] | ||
?.takeIf { it.isValid(modificationStamp) } | ||
?: CachedOwner(if (isDocComment) documentationOwner else null, modificationStamp) | ||
.also { DOCUMENTATION_OWNER_CACHE[this@cachedOwner] = it } | ||
} | ||
|
||
/** | ||
* 文档注释所有者 | ||
*/ | ||
protected open val T.documentationOwner: PsiElement? get() = super.getDocumentationOwner(this) | ||
|
||
/** | ||
* 缓存的注释所有者 | ||
* | ||
* @property owner 注释所有者 | ||
* @property modificationStamp 修改标记 | ||
* | ||
* @see PsiFile.getModificationStamp | ||
*/ | ||
protected data class CachedOwner(val owner: PsiElement?, val modificationStamp: Long) { | ||
/** | ||
* 通过指定的[修改标记][modificationStamp]检测当前缓存是否有效 | ||
* | ||
* @see PsiFile.getModificationStamp | ||
*/ | ||
fun isValid(modificationStamp: Long): Boolean { | ||
return this.modificationStamp == modificationStamp && (owner?.isValid ?: true) | ||
} | ||
} | ||
|
||
protected companion object { | ||
val DOCUMENTATION_OWNER_CACHE = Key.create<CachedOwner?>("DOCUMENTATION_OWNER_CACHE") | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 24 additions & 33 deletions
57
src/main/kotlin/cn/yiiguxing/plugin/translate/provider/GoDocumentationElementProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,43 @@ | ||
package cn.yiiguxing.plugin.translate.provider | ||
|
||
import cn.yiiguxing.plugin.translate.util.elementType | ||
import cn.yiiguxing.plugin.translate.util.findChildOfType | ||
import cn.yiiguxing.plugin.translate.util.getNextSiblingSkippingCondition | ||
import com.goide.psi.* | ||
import com.intellij.psi.PsiComment | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.PsiFile | ||
import com.intellij.psi.PsiWhiteSpace | ||
|
||
class GoDocumentationElementProvider : DocumentationElementProvider { | ||
class GoDocumentationElementProvider : AbstractDocumentationElementProvider<PsiComment>() { | ||
|
||
override fun findDocumentationElementAt(psiFile: PsiFile, offset: Int): PsiElement? { | ||
val element = psiFile.findElementAt(offset) | ||
return (element as? PsiComment)?.takeIf { it.owner != null } | ||
} | ||
override val PsiComment.isDocComment: Boolean | ||
get() = true | ||
|
||
override fun getDocumentationOwner(documentationElement: PsiElement): PsiElement? { | ||
return (documentationElement as? PsiComment)?.owner | ||
} | ||
override val PsiComment.isPickAtEdge: Boolean | ||
get() = elementType.toString() === "GO_LINE_COMMENT" | ||
|
||
override val PsiComment.documentationOwner: PsiElement? | ||
get() = when (val element = getNextSiblingSkippingCondition(SKIP_WHITE_SPACE_AND_COMMENT)) { | ||
null -> null | ||
|
||
is GoPackageClause -> element.takeIf { parent is GoFile } | ||
is GoMethodSpec, is GoFunctionOrMethodDeclaration -> element | ||
|
||
else -> when (element) { | ||
is GoTypeDeclaration -> GoTypeSpec::class.java to false | ||
is GoFieldDeclaration -> GoFieldDefinition::class.java to false | ||
is GoConstDeclaration -> GoConstDefinition::class.java to true | ||
is GoVarDeclaration -> GoVarDefinition::class.java to true | ||
else -> null | ||
}?.let { (type, depth) -> | ||
element.findChildOfType(type, depth) | ||
} | ||
} | ||
|
||
private companion object { | ||
val SKIP_WHITE_SPACE_AND_COMMENT: (PsiElement) -> Boolean = { | ||
(it is PsiWhiteSpace && it.text.count { char -> char == '\n' } <= 1) || it is PsiComment | ||
} | ||
|
||
val GoTypeDeclaration.innerOwner: PsiElement? | ||
get() = findChildOfType(GoTypeSpec::class.java) | ||
|
||
val GoVarDeclaration.innerOwner: PsiElement? | ||
get() = findChildOfType(GoVarDefinition::class.java, true) | ||
|
||
val PsiComment.owner: PsiElement? | ||
get() { | ||
val element = getNextSiblingSkippingCondition(SKIP_WHITE_SPACE_AND_COMMENT) | ||
|
||
println(element) | ||
println(element is GoMethodSpec) | ||
println(element?.javaClass?.name) | ||
|
||
return when (element) { | ||
is GoPackageClause -> element.takeIf { parent is GoFile } | ||
is GoTypeDeclaration -> element.innerOwner | ||
is GoMethodDeclaration -> element | ||
is GoMethodSpec -> element | ||
is GoVarDeclaration -> element.innerOwner | ||
else -> null | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters