1
+ package com.github.oldmegit.goframeidea.goFrame
2
+
3
+ import com.goide.psi.*
4
+ import com.goide.psi.impl.GoPsiUtil
5
+ import com.intellij.psi.PsiComment
6
+ import com.intellij.psi.PsiElement
7
+ import com.intellij.psi.ResolveState
8
+ import com.intellij.psi.util.PsiTreeUtil
9
+ import com.intellij.util.ObjectUtils
10
+
11
+ object OrmUtil {
12
+ // get statement contain XXXDao by given PsiElement
13
+ fun getStatementContainDao (psiElement : PsiElement ): GoStatement ? {
14
+ // get direct statement
15
+ var statement = PsiTreeUtil .findFirstParent(psiElement) { e: PsiElement ? ->
16
+ e is GoStatement
17
+ } as GoStatement ?
18
+
19
+ if (statement is GoAssignmentStatement ) {
20
+ statement = doAssignmentStatement(statement)
21
+ } else if (statement is GoSimpleStatement ) {
22
+ statement = doSimpleStatement(statement)
23
+ }
24
+
25
+ return statement
26
+ }
27
+
28
+ // get Xxx dao by statement
29
+ fun getDaoByStatement (statement : GoStatement ): GoStructType ? {
30
+ for (callExpr in PsiTreeUtil .findChildrenOfType(statement, GoCallExpr ::class .java)) {
31
+ val reference = GoPsiUtil .getCallReference(callExpr)
32
+ // get the declaration of fun
33
+ val declaration = ObjectUtils .tryCast(
34
+ reference!! .resolve(),
35
+ GoMethodDeclaration ::class .java
36
+ )
37
+
38
+ // get the return type of fun's declaration
39
+ var resultType = declaration!! .resultType
40
+
41
+ // get the gotype if return type is gotype pointer
42
+ // resultType is Model or gdb.Model
43
+ if (resultType is GoPointerType ) {
44
+ resultType = resultType.type!!
45
+ }
46
+
47
+ if (resultType.resolve(ResolveState .initial()) !is GoTypeSpec ) {
48
+ continue
49
+ }
50
+
51
+ val pointerType = declaration.receiver!! .type
52
+ if (pointerType !is GoPointerType ) {
53
+ continue
54
+ }
55
+ val type = pointerType.type ? : return null
56
+ if (! type.text?.endsWith(" Dao" )!! ) {
57
+ continue
58
+ }
59
+
60
+ val spec = type.resolve(ResolveState .initial())
61
+ if (spec is GoTypeSpec ) {
62
+ return spec.specType.type as GoStructType
63
+ }
64
+ }
65
+ return null
66
+ }
67
+
68
+ // get column GoType by XxxDao of type GoStructType
69
+ fun getColumnByDao (structType : GoStructType ): GoType ? {
70
+ for (field in structType.fieldDeclarationList) {
71
+ val name = field.fieldDefinitionList[0 ].name?.lowercase()
72
+ if (name?.endsWith(" columns" )!! ) {
73
+ return field.type
74
+ }
75
+ }
76
+ return null
77
+ }
78
+
79
+ // get table data by XXXColumns of type GoTypeSpec
80
+ fun getTableData (columnType : GoType ): Map <String , String > {
81
+ val typeSpec = columnType.resolve(ResolveState .initial()) as GoTypeSpec
82
+ val fields = PsiTreeUtil .findChildrenOfType(typeSpec, GoFieldDeclaration ::class .java)
83
+ val data: MutableMap <String , String > = hashMapOf()
84
+ for (field in fields) {
85
+ val fieldDefinition = field.firstChild
86
+ if (fieldDefinition !is GoFieldDefinition ) {
87
+ continue
88
+ }
89
+ val psiComment = field.nextSibling.nextSibling
90
+ var comment = " "
91
+ if (psiComment is PsiComment ) {
92
+ comment = extractTextFromComment(psiComment.text)
93
+ }
94
+ data[fieldDefinition.text.camelToSnakeCase()] = comment
95
+ }
96
+ return data
97
+ }
98
+
99
+ // handle type GoAssignmentStatement
100
+ // for example:
101
+ // db = db.Xxx
102
+ private fun doAssignmentStatement (assignmentStatement : GoAssignmentStatement ): GoStatement ? {
103
+ for (expression in assignmentStatement.leftHandExprList.expressionList) {
104
+ val psiElementRoot = expression.reference?.resolve()
105
+ return getStatementContainDao(psiElementRoot!! )
106
+ }
107
+ return null
108
+ }
109
+
110
+ // handle type GoSimpleStatement
111
+ // for example:
112
+ // db := db.Xxx
113
+ // db.Xxx or dao.Xxx
114
+ private fun doSimpleStatement (simpleStatement : GoSimpleStatement ): GoStatement ? {
115
+ val declaration = simpleStatement.shortVarDeclaration
116
+ // direct return if db := db.Xxx
117
+ if (declaration != null ) {
118
+ return simpleStatement
119
+ }
120
+
121
+ // db.Xxx
122
+ val list = PsiTreeUtil .findChildrenOfType(simpleStatement, GoReferenceExpression ::class .java)
123
+ val last = list.last()
124
+ if (last.resolve() is GoVarDefinition ) {
125
+ return getStatementContainDao(last.resolve() as GoVarDefinition )
126
+ }
127
+
128
+ return null
129
+ }
130
+
131
+ private fun extractTextFromComment (comment : String ): String {
132
+ if (! comment.startsWith(" //" )) {
133
+ return comment
134
+ }
135
+ if (comment == " //" ) {
136
+ return " "
137
+ }
138
+ return comment.drop(2 )
139
+ }
140
+
141
+ // camel to snake case
142
+ private fun String.camelToSnakeCase (): String {
143
+ val regex = " (?<=[a-zA-Z])[A-Z]" .toRegex()
144
+ return regex.replace(this ) { " _${it.value} " }.lowercase()
145
+ }
146
+ }
0 commit comments