Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
YiiGuxing committed Jan 13, 2020
2 parents eb3e6b1 + e7838be commit 93220e2
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 84 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change Log

## [v2.7.1](https://github.com/YiiGuxing/TranslationPlugin/tree/v2.7.1) (2020-01-13)

- 优化了单行文档注释的交互体验
- 修复了Go语言在一些情况下无法进行文档翻译的问题

## [v2.7.0](https://github.com/YiiGuxing/TranslationPlugin/tree/v2.7.0) (2020-01-08)

- 新增对Go, Dart, Python, C, C++, Objective-C/C++语言的文档注释翻译支持
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,10 @@ FAQ
更新日志
--------

## [v2.7.0](https://github.com/YiiGuxing/TranslationPlugin/tree/v2.7.0) (2020-01-08)
## [v2.7.1](https://github.com/YiiGuxing/TranslationPlugin/tree/v2.7.1) (2020-01-13)

- 新增对Go, Dart, Python, C, C++, Objective-C/C++语言的文档注释翻译支持
- 支持列选择模式的翻译
- 优化了单行文档注释的交互体验
- 修复了Go语言在一些情况下无法进行文档翻译的问题

[完整的更新历史记录](./CHANGELOG.md)

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# suppress inspection "UnusedProperty" for whole file
version=2.7.0
version=2.7.1
buildNumber=
ideaVersion=IU-2017.1
javaVersion=1.8
Expand Down
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")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,37 @@ import cn.yiiguxing.plugin.translate.util.getNextSiblingSkippingCondition
import cn.yiiguxing.plugin.translate.util.getPrevSiblingSkippingCondition
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiWhiteSpace
import com.jetbrains.lang.dart.DartTokenTypesSets
import com.jetbrains.lang.dart.psi.DartComponent
import com.jetbrains.lang.dart.psi.DartComponentName
import com.jetbrains.lang.dart.psi.DartDocComment
import com.jetbrains.lang.dart.psi.DartVarDeclarationList

class DartDocumentationElementProvider : DocumentationElementProvider {
class DartDocumentationElementProvider : AbstractDocumentationElementProvider<PsiComment>() {

override fun findDocumentationElementAt(psiFile: PsiFile, offset: Int): PsiElement? {
val element = psiFile.findElementAt(offset) ?: return null
val type = element.elementType
val docElement = when {
element is PsiComment && type == DartTokenTypesSets.SINGLE_LINE_DOC_COMMENT -> element
element.parent is DartDocComment -> element.parent
else -> return null
} as PsiComment
override val PsiComment.isDocComment: Boolean
get() = this@isDocComment is DartDocComment || elementType == DartTokenTypesSets.SINGLE_LINE_DOC_COMMENT

return docElement.takeIf { it.owner != null }
}
override val PsiComment.isPickAtEdge: Boolean
get() = elementType == DartTokenTypesSets.SINGLE_LINE_DOC_COMMENT

override fun getDocumentationOwner(documentationElement: PsiElement): PsiElement? {
return (documentationElement as? PsiComment)?.owner
}
override val PsiComment.documentationOwner: PsiElement?
get() {
// 文档注释类型中,多行注释有最高的优先级。
// 如果当前注释不是多行注释(DartDocComment),则向上寻找,如果上方有多行注释,则说明当前的注释是无效的。
// 且,最下方的多行文档注释有最高的优先级,向下寻找时如遇文档注释,则当前的注释也是无效的。

if (this !is DartDocComment && !checkPreviousComments()) {
return null
}

return when (val sibling = getNextSiblingSkippingCondition(SKIPPING_CONDITION)) {
is DartComponent -> sibling.componentName
is DartVarDeclarationList -> sibling.findChildOfType(DartComponent::class.java)?.componentName
else -> null
}
}

companion object {
private val SKIPPING_CONDITION: (PsiElement) -> Boolean = {
Expand All @@ -45,25 +51,5 @@ class DartDocumentationElementProvider : DocumentationElementProvider {
private fun PsiComment.checkPreviousComments(): Boolean {
return getPrevSiblingSkippingCondition(SKIPPING_CONDITION) !is DartDocComment
}

/**
* 找到注释目标
*/
private val PsiComment.owner: PsiElement?
get() {
// 文档注释类型中,多行注释有最高的优先级。
// 如果当前注释不是多行注释(DartDocComment),则向上寻找,如果上方有多行注释,则说明当前的注释是无效的。
// 且,最下方的多行文档注释有最高的优先级,向下寻找时如遇文档注释,则当前的注释也是无效的。

if (this !is DartDocComment && !checkPreviousComments()) {
return null
}

return when (val sibling = getNextSiblingSkippingCondition(SKIPPING_CONDITION)) {
is DartComponent -> sibling.componentName
is DartVarDeclarationList -> sibling.findChildOfType(DartComponent::class.java)?.componentName
else -> null
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface DocumentationElementProvider {

override fun findDocumentationElementAt(psiFile: PsiFile, offset: Int): PsiElement? {
return psiFile.findElementOfTypeAt(offset, PsiDocCommentBase::class.java)
?.takeIf { it.owner != null }
}

}
Expand Down
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
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ package cn.yiiguxing.plugin.translate.provider

import cn.yiiguxing.plugin.translate.util.findChild
import cn.yiiguxing.plugin.translate.util.getNextSiblingSkippingCondition
import com.intellij.psi.*
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiDocCommentBase
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import com.jetbrains.cidr.lang.psi.OCDeclaration
import com.jetbrains.cidr.lang.psi.OCDeclarationStatement
import com.jetbrains.cidr.lang.psi.OCStruct
import com.jetbrains.cidr.lang.types.OCStructType

class ObjectiveCDocumentationElementProvider : DocumentationElementProvider {
class ObjectiveCDocumentationElementProvider : AbstractDocumentationElementProvider<PsiDocCommentBase>() {

override fun findDocumentationElementAt(psiFile: PsiFile, offset: Int): PsiElement? {
val element = psiFile.findElementAt(offset)
return (element as? PsiDocCommentBase)?.takeIf { it.innerOwner != null }
}
override val PsiDocCommentBase.isDocComment: Boolean
get() = true

override fun getDocumentationOwner(documentationElement: PsiElement): PsiElement? {
return (documentationElement as? PsiDocCommentBase)?.innerOwner
}
override val PsiDocCommentBase.documentationOwner: PsiElement?
get() = innerOwner

companion object {
private val IS_OC_STRUCT: (PsiElement) -> Boolean = { it is OCStruct }
Expand Down
12 changes: 11 additions & 1 deletion src/main/kotlin/cn/yiiguxing/plugin/translate/util/PSI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,22 @@ val SKIP_WHITE_SPACE: (PsiElement) -> Boolean = { it is PsiWhiteSpace }
*/
val PsiElement.elementType: IElementType get() = node.elementType

/**
* 开始偏移
*/
val PsiElement.startOffset: Int get() = textRange.startOffset

/**
* 结束偏移
*/
val PsiElement.endOffset: Int get() = textRange.endOffset

/**
* 从[PsiFile]中在指定[offset]处查找类型为[type]的元素并返回,如果未找到则返回`null`
*/
fun <T : PsiElement> PsiFile.findElementOfTypeAt(offset: Int, type: Class<T>): T? {
val offsetElement = findElementAt(offset) ?: return null
return PsiTreeUtil.getParentOfType(offsetElement, type)
return PsiTreeUtil.getParentOfType(offsetElement, type, false)
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@

<change-notes><![CDATA[
<ul>
<li>新增对Go, Dart, Python, C, C++, Objective-C/C++语言的文档注释翻译支持</li>
<li>支持列选择模式的翻译</li>
<li>优化了单行文档注释的交互体验</li>
<li>修复了Go语言在一些情况下无法进行文档翻译的问题</li>
</ul>
<a href="https://github.com/YiiGuxing/TranslationPlugin/blob/master/CHANGELOG.md"><b>Full Changelog History</b></a>
]]></change-notes>
Expand Down

0 comments on commit 93220e2

Please sign in to comment.