Skip to content

Commit a435219

Browse files
committed
fix(main): 修复模板存在重复代码块、多空行时,代理断点映射行错误的问题
1 parent f92a958 commit a435219

7 files changed

Lines changed: 110 additions & 37 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
Changelog
22
=========
33

4+
## 0.2.4
5+
* fix(main): 修复模板存在重复代码块、多空行时,代理断点映射行错误的问题
6+
47
## 0.1
58
* 项目初始化

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ org.gradle.caching = true
55
pluginGroup = io.maliboot.www
66
pluginName = Hyperf Support
77

8-
pluginVersion = 0.2
8+
pluginVersion = 0.2.4
99

1010
pluginSinceBuild = 231
1111
pluginUntilBuild =

src/main/kotlin/io/maliboot/www/hyperf/common/extend/LighterASTExt.kt

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.intellij.lang.LighterASTNode
55
import com.intellij.psi.impl.source.tree.LightTreeUtil
66
import com.intellij.psi.impl.source.tree.RecursiveLighterASTNodeWalkingVisitor
77
import com.intellij.psi.tree.IElementType
8+
import com.intellij.ui.treeStructure.Tree
89
import com.jetbrains.php.lang.lexer.PhpTokenTypes
910
import com.jetbrains.php.lang.parser.PhpElementTypes
1011

@@ -45,6 +46,69 @@ fun LighterAST.getMethodLightASTNode(methodName: String): LighterASTNode? {
4546
return resultNode
4647
}
4748

49+
fun LighterAST.findFirstChildLightASTNode(
50+
parentASTNode: LighterASTNode,
51+
startOffset: Int
52+
): LighterASTNode? {
53+
if (startOffset < parentASTNode.startOffset) {
54+
return null
55+
}
56+
57+
var resultNode: LighterASTNode? = null
58+
object : RecursiveLighterASTNodeWalkingVisitor(this) {
59+
override fun visitNode(element: LighterASTNode) {
60+
if (element.startOffset > startOffset) {
61+
resultNode = element
62+
super.stopWalking()
63+
return
64+
}
65+
super.visitNode(element)
66+
}
67+
}.visitNode(parentASTNode)
68+
return resultNode
69+
}
70+
71+
fun LighterAST.getTreeIndexPath(
72+
parentASTNode: LighterASTNode,
73+
childASTNode: LighterASTNode,
74+
deepMax: Int = 500
75+
): MutableList<Int>? {
76+
var count = deepMax
77+
var myChildNode = childASTNode
78+
79+
val path: MutableList<Int> = mutableListOf()
80+
while (count >= 0) {
81+
val myParentNode = this.getParent(myChildNode) ?: return null
82+
// 追加path index
83+
path.add(0, this.getChildren(myParentNode).indexOf(myChildNode))
84+
// 遍历完成
85+
if (myParentNode == parentASTNode) {
86+
break
87+
}
88+
// 下一轮
89+
myChildNode = myParentNode
90+
count--
91+
}
92+
if (path.isEmpty()) {
93+
return null
94+
}
95+
return path
96+
}
97+
98+
fun LighterAST.getChildByTreeIndexPath(parentASTNode: LighterASTNode, treeIndexPath: List<Int>): LighterASTNode? {
99+
var currentIndex = 0
100+
var myParentNode = parentASTNode
101+
102+
while (currentIndex < treeIndexPath.size) {
103+
myParentNode = this.getChildren(myParentNode).takeIf {
104+
it.size > treeIndexPath[currentIndex]
105+
}?.get(treeIndexPath[currentIndex]) ?: return null
106+
currentIndex++
107+
}
108+
109+
return myParentNode
110+
}
111+
48112
fun LighterAST.getChildrenOfType(node: LighterASTNode, type: IElementType): LighterASTNode? {
49113
return LightTreeUtil.getChildrenOfType(this, node, type)
50114
.takeIf { it.isNotEmpty() }
@@ -57,14 +121,24 @@ fun LighterAST.getNodeText(node: LighterASTNode, type: IElementType = PhpTokenTy
57121
}
58122
}
59123

124+
fun LighterAST.getGroupStmtNode(parentASTNode: LighterASTNode): LighterASTNode? {
125+
return getChildrenOfType(parentASTNode, PhpElementTypes.GROUP_STATEMENT)
126+
}
127+
60128
fun LighterAST.getHyperfProxyClosure(methodNode: LighterASTNode): LighterASTNode? {
61129
getChildrenOfType(methodNode, PhpElementTypes.GROUP_STATEMENT)?.let { groupStmtNode->
62130
getChildrenOfType(groupStmtNode, PhpElementTypes.RETURN)?.let { groupStmtReturnNode ->
63131
getChildrenOfType(groupStmtReturnNode, PhpElementTypes.METHOD_REFERENCE)?.takeIf {
64132
// 查找 hyperf -> self::__proxyCall
65133
getNodeText(it) == "__proxyCall"
66-
}?.let {
67-
return it
134+
}
135+
}
136+
}?.let{ selfProxyCall ->
137+
getChildrenOfType(selfProxyCall, PhpElementTypes.PARAMETER_LIST)?.let { selfProxyCallParameterList ->
138+
getChildrenOfType(selfProxyCallParameterList, PhpElementTypes.CLOSURE)?.let { proxyClosure ->
139+
getChildrenOfType(proxyClosure, PhpElementTypes.FUNCTION)?.let {
140+
return it
141+
}
68142
}
69143
}
70144
}

src/main/kotlin/io/maliboot/www/hyperf/debug/HyperfProxyPathMapper.kt

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import com.intellij.xdebugger.XSourcePosition
99
import com.jetbrains.php.debug.template.PhpTemplateDebugStateService
1010
import com.jetbrains.php.debug.template.PhpTemplateLanguagePathMapper
1111
import com.jetbrains.php.lang.PhpFileType
12-
import com.jetbrains.php.lang.parser.PhpElementTypes
1312
import com.jetbrains.php.util.pathmapper.PhpPathMapper
1413
import io.maliboot.www.hyperf.common.extend.*
1514

@@ -67,50 +66,59 @@ class HyperfProxyPathMapper : PhpTemplateLanguagePathMapper() {
6766
// 代理文件
6867
val proxyFile = originPos.file.getHyperfProxyFile(project) ?: return null
6968

70-
// 原文件-获取类方法GroupStmt的开始行
69+
// 模板文件
7170
val originTree = originPos.file.findPsiFile(project)?.node?.lighterAST ?: return null
7271
val originMethodNode = originTree.getMethodLightASTNode(originPos.offset) ?: return null
7372
val classMethodName = originTree.getNodeText(originMethodNode) ?: return null
74-
val originFuncStartLine = originTree
75-
.getChildrenOfType(originMethodNode, PhpElementTypes.GROUP_STATEMENT)
76-
?.getStartLineNumber(originPos.file)
77-
?: return null
73+
// 获取方法与断点之间的treePath
74+
val sourcePosRelativeTreePath =
75+
originTree.getGroupStmtNode(originMethodNode)?.let { originMethodGroupStmtNode ->
76+
originTree.findFirstChildLightASTNode(originMethodGroupStmtNode, originPos.offset)?.let {
77+
originTree.getTreeIndexPath(originMethodGroupStmtNode, it)
78+
}
79+
} ?: return null
7880

7981
// 代理文件位置
8082
val proxyTree = proxyFile.findPsiFile(project)?.node?.lighterAST ?: return null
8183
proxyTree.getMethodLightASTNode(classMethodName)?.let { proxyMethodNode ->
8284
// 排除AOP代码干扰
8385
proxyTree.getHyperfProxyClosure(proxyMethodNode) ?: proxyMethodNode
84-
}?.getStartLineNumber(proxyFile)?.let {
85-
it + (originPos.line - originFuncStartLine)
8686
}?.let {
87-
return XDebuggerUtil.getInstance().createPosition(proxyFile, it)
87+
proxyTree.getGroupStmtNode(it)
88+
}?.let {
89+
proxyTree.getChildByTreeIndexPath(it, sourcePosRelativeTreePath)
90+
}?.let {
91+
return XDebuggerUtil.getInstance().createPositionByOffset(proxyFile, it.startOffset)
8892
}
8993

9094
return null
9195
}
9296

9397
private fun guessOriginXSourcePosition(proxyPos: XSourcePosition, project: Project): XSourcePosition? {
94-
// 获取原文件
98+
// 获取模板
9599
val originFile = proxyPos.file.getHyperfOriginFile(project) ?: return null
96100

97101
// 代理文件-获取类方法[代理闭包]GroupStmt的开始行
98102
val proxyTree = proxyPos.file.findPsiFile(project)?.node?.lighterAST ?: return null
99103
val proxyMethodNode = proxyTree.getMethodLightASTNode(proxyPos.offset) ?: return null
100104
val classMethodName = proxyTree.getNodeText(proxyMethodNode) ?: return null
101-
val proxyFuncStartLine = proxyTree.getChildrenOfType(proxyMethodNode, PhpElementTypes.GROUP_STATEMENT)
102-
?.getStartLineNumber(proxyPos.file)?.let {
103-
proxyTree.getHyperfProxyClosure(proxyMethodNode)?.getStartLineNumber(proxyPos.file) ?: it
104-
} ?: return null
105-
106-
// 原文件位置
105+
// 获取方法与断点之间的treePath
106+
val sourcePosRelativeTreePath = (proxyTree.getHyperfProxyClosure(proxyMethodNode) ?: proxyMethodNode).let {
107+
proxyTree.getGroupStmtNode(it)
108+
}?.let { funcNode ->
109+
proxyTree.findFirstChildLightASTNode(funcNode, proxyPos.offset)?.let {
110+
proxyTree.getTreeIndexPath(funcNode, it)
111+
}
112+
} ?: return null
113+
114+
// 模板位置
107115
val originTree = originFile.findPsiFile(project)?.node?.lighterAST ?: return null
108116
originTree.getMethodLightASTNode(classMethodName)?.let {
109-
originTree.getChildrenOfType(it, PhpElementTypes.GROUP_STATEMENT)
110-
}?.getStartLineNumber(originFile)?.let {
111-
it + (proxyPos.line - proxyFuncStartLine)
117+
originTree.getGroupStmtNode(it)
118+
}?.let {
119+
originTree.getChildByTreeIndexPath(it, sourcePosRelativeTreePath)
112120
}?.let {
113-
return XDebuggerUtil.getInstance().createPosition(originFile, it)
121+
return XDebuggerUtil.getInstance().createPositionByOffset(originFile, it.startOffset)
114122
}
115123

116124
return null
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<html>
22
<ul>
3-
<li>Initial Plugin</li>
3+
<li>fix(main): 修复模板存在重复代码块、多空行时,代理断点映射行错误的问题</li>
44
</ul>
55
</html>

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@
2323
<errorHandler implementation="io.maliboot.www.hyperf.GithubErrorReporter"/>
2424
</extensions>
2525
<extensions defaultExtensionNs="com.intellij.php">
26-
<debug.templateLanguage implementation="io.maliboot.www.hyperf.debug.HyperfProxyPathMapper"/>
26+
<debug.templateLanguage implementation="io.maliboot.www.hyperf.debug.HyperfProxyPathMapper" order="first"/>
2727
</extensions>
2828
</idea-plugin>

src/main/resources/META-INF/pluginIcon.svg

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)