Skip to content

Commit dac1126

Browse files
committed
Modifying bind variable fields in function calls
1 parent 931ab48 commit dac1126

File tree

2 files changed

+66
-42
lines changed

2 files changed

+66
-42
lines changed

src/main/kotlin/org/domaframework/doma/intellij/contributor/sql/provider/SqlParameterCompletionProvider.kt

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
119119
val blockElements = getAccessElementTextBlocks(originalPosition)
120120
generateCompletionList(
121121
blockElements,
122-
pos.text,
122+
pos,
123123
originalFile,
124124
result,
125125
)
@@ -163,7 +163,11 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
163163
var blocks: List<PsiElement> = emptyList()
164164
// If the immediate parent is a for, if, elseif directive,
165165
// get the field access element list from its own forward element.
166-
val parent = targetElement.parent
166+
val parent =
167+
PsiTreeUtil.findFirstParent(targetElement) {
168+
it.elementType != SqlTypes.EL_ID_EXPR &&
169+
it.elementType != SqlTypes.EL_IDENTIFIER
170+
}
167171
if (parent is SqlElForDirective ||
168172
parent is SqlElIfDirective ||
169173
parent is SqlElElseifDirective
@@ -202,7 +206,15 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
202206
var parameterParent: PsiElement? =
203207
PsiTreeUtil.getParentOfType(targetElement, SqlElParameters::class.java)
204208
if (parameterParent != null) {
205-
blocks = emptyList()
209+
val children = mutableListOf<PsiElement>()
210+
parameterParent.children.forEach { child ->
211+
if (child is SqlElFieldAccessExpr) {
212+
children.addAll(child.children)
213+
} else {
214+
child.add(child)
215+
}
216+
}
217+
return children
206218
} else {
207219
// Completion for subsequent arguments
208220
parameterParent =
@@ -217,7 +229,24 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
217229
) != null
218230
}
219231
if (parameterParent != null) {
220-
blocks = emptyList()
232+
val errorElement = targetElement.prevLeafs.firstOrNull { it is PsiErrorElement }
233+
if (errorElement != null) {
234+
parameterParent = (errorElement.parent as? SqlElParameters)
235+
val children = mutableListOf<PsiElement>()
236+
parameterParent
237+
?.children
238+
?.reversed()
239+
?.takeWhile {
240+
it.nextSibling?.elementType != SqlTypes.COMMA
241+
}?.forEach { child ->
242+
if (child is SqlElFieldAccessExpr) {
243+
children.addAll(child.children)
244+
} else {
245+
children.add(child)
246+
}
247+
}
248+
blocks = children.reversed().takeWhile { it.nextSibling?.elementType != SqlTypes.COMMA }
249+
}
221250
}
222251
}
223252
}
@@ -240,17 +269,17 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
240269
*/
241270
private fun generateCompletionList(
242271
elements: List<PsiElement>,
243-
positionText: String,
272+
position: PsiElement,
244273
originalFile: PsiFile,
245274
result: CompletionResultSet,
246275
) {
247-
val searchText = cleanString(positionText)
276+
val searchText = cleanString(getSearchElementText(position))
248277
var topElementType: PsiType? = null
249-
val top =
250-
when {
251-
elements.isEmpty() -> return
252-
else -> elements.first()
253-
}
278+
if (elements.isEmpty()) {
279+
getElementTypeByFieldAccess(originalFile, elements, result)
280+
return
281+
}
282+
val top = elements.first()
254283

255284
val topText = cleanString(getSearchElementText(top))
256285
val prevWord = PsiPatternUtil.getBindSearchWord(originalFile, elements.last(), " ")
@@ -268,7 +297,7 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
268297
if (topElementType == null) {
269298
if (isFieldAccessByForItem(top, elements, searchText, result)) return
270299
topElementType =
271-
getElementTypeByFieldAccess(originalFile, topText, elements, result) ?: return
300+
getElementTypeByFieldAccess(originalFile, elements, result) ?: return
272301
}
273302

274303
val fieldAccessorChildElementValidator =
@@ -320,9 +349,9 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
320349
setFieldsAndMethodsCompletionResultSet(matchFields, matchMethod, result)
321350
}
322351

323-
private fun getSearchElementText(elm: PsiElement): String =
324-
if (elm.elementType == SqlTypes.EL_IDENTIFIER) {
325-
elm.text
352+
private fun getSearchElementText(elm: PsiElement?): String =
353+
if (elm is SqlElIdExpr || elm.elementType == SqlTypes.EL_IDENTIFIER) {
354+
elm?.text ?: ""
326355
} else {
327356
""
328357
}
@@ -357,20 +386,23 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
357386
*/
358387
private fun getElementTypeByFieldAccess(
359388
originalFile: PsiFile,
360-
topText: String,
361389
elements: List<PsiElement>,
362390
result: CompletionResultSet,
363391
): PsiType? {
364392
val daoMethod = findDaoMethod(originalFile) ?: return null
393+
val topText = cleanString(getSearchElementText(elements.firstOrNull()))
365394
val matchParams = daoMethod.searchParameter(topText)
366-
val firstElement = matchParams.firstOrNull() ?: return null
367-
if (elements.isEmpty() || elements.size <= 1) {
395+
val findParam = matchParams.find { it.name == topText }
396+
if (elements.size <= 1 && findParam == null) {
368397
matchParams.map { match ->
369398
result.addElement(LookupElementBuilder.create(match.name))
370399
}
371400
return null
372401
}
373-
val immediate = firstElement.getIterableClazz(daoMethod.getDomaAnnotationType())
402+
if (findParam == null) {
403+
return null
404+
}
405+
val immediate = findParam.getIterableClazz(daoMethod.getDomaAnnotationType())
374406
return immediate.type
375407
}
376408

src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiElementExtension.kt

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,41 +17,33 @@ package org.domaframework.doma.intellij.extension.psi
1717

1818
import com.intellij.psi.PsiDirectory
1919
import com.intellij.psi.PsiElement
20+
import com.intellij.psi.PsiErrorElement
2021
import com.intellij.psi.PsiFile
2122
import com.intellij.psi.PsiWhiteSpace
2223
import com.intellij.psi.tree.IElementType
2324
import com.intellij.psi.util.elementType
2425
import com.intellij.psi.util.prevLeafs
25-
import org.domaframework.doma.intellij.psi.SqlElParameters
26+
import org.domaframework.doma.intellij.psi.SqlElIdExpr
2627
import org.domaframework.doma.intellij.psi.SqlTypes
2728

2829
fun PsiElement.isNotWhiteSpace(): Boolean = this !is PsiWhiteSpace
2930

3031
// Get the list of elements before itself
3132
fun PsiElement.findSelfBlocks(): List<PsiElement> {
32-
var elms = emptyList<PsiElement>()
33-
for (it in this.prevLeafs) {
34-
// When performing code completion within a [SqlElParameter] element,
35-
// there is a possibility that a “)” may be inserted for the final argument, so it is excluded.
36-
elms = elms.plus(it)
37-
if (!it.isNotWhiteSpace() ||
38-
it.elementType == SqlTypes.AT_SIGN ||
39-
(it.elementType == SqlTypes.LEFT_PAREN && it.parent !is SqlElParameters) ||
40-
it.elementType == SqlTypes.COMMA
41-
) {
42-
break
43-
}
44-
}
33+
val elms =
34+
this.prevLeafs
35+
.takeWhile {
36+
it.isNotWhiteSpace() &&
37+
it.elementType != SqlTypes.AT_SIGN &&
38+
(it.elementType != SqlTypes.LEFT_PAREN || it.parent.elementType == SqlTypes.EL_PARAMETERS) &&
39+
it.elementType != SqlTypes.COMMA
40+
}.toList()
41+
.plus(this)
42+
.filter { it is PsiErrorElement || it is SqlElIdExpr || it.elementType == SqlTypes.EL_IDENTIFIER }
43+
.filter { it.isNotWhiteSpace() }
44+
.sortedBy { it.textOffset }
4545

46-
elms
47-
.filter { it.elementType == SqlTypes.EL_IDENTIFIER }
48-
.toList()
49-
.plus(this)
50-
.also { elms = it }
51-
if (elms.isNotEmpty()) {
52-
return elms.sortedBy { it.textOffset }
53-
}
54-
return emptyList()
46+
return if (elms.isNotEmpty()) elms else emptyList()
5547
}
5648

5749
/**

0 commit comments

Comments
 (0)