Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,29 +46,21 @@ import org.domaframework.doma.intellij.common.util.PluginLoggerUtil
import org.domaframework.doma.intellij.common.util.SqlCompletionUtil.createMethodLookupElement
import org.domaframework.doma.intellij.extension.getJavaClazz
import org.domaframework.doma.intellij.extension.psi.findNodeParent
import org.domaframework.doma.intellij.extension.psi.findSelfBlocks
import org.domaframework.doma.intellij.extension.psi.findStaticField
import org.domaframework.doma.intellij.extension.psi.findStaticMethod
import org.domaframework.doma.intellij.extension.psi.isNotWhiteSpace
import org.domaframework.doma.intellij.extension.psi.searchParameter
import org.domaframework.doma.intellij.extension.psi.searchStaticField
import org.domaframework.doma.intellij.extension.psi.searchStaticMethod
import org.domaframework.doma.intellij.psi.SqlElAndExpr
import org.domaframework.doma.intellij.psi.SqlElClass
import org.domaframework.doma.intellij.psi.SqlElElseifDirective
import org.domaframework.doma.intellij.psi.SqlElEqExpr
import org.domaframework.doma.intellij.psi.SqlElFieldAccessExpr
import org.domaframework.doma.intellij.psi.SqlElForDirective
import org.domaframework.doma.intellij.psi.SqlElGeExpr
import org.domaframework.doma.intellij.psi.SqlElGtExpr
import org.domaframework.doma.intellij.psi.SqlElIdExpr
import org.domaframework.doma.intellij.psi.SqlElIfDirective
import org.domaframework.doma.intellij.psi.SqlElLeExpr
import org.domaframework.doma.intellij.psi.SqlElLtExpr
import org.domaframework.doma.intellij.psi.SqlElNeExpr
import org.domaframework.doma.intellij.psi.SqlElOrExpr
import org.domaframework.doma.intellij.psi.SqlElParameters
import org.domaframework.doma.intellij.psi.SqlTypes
import kotlin.collections.emptyList

class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
Expand Down Expand Up @@ -111,13 +103,6 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(

if (!isDirective) {
// Check when performing code completion on the right side
val prevElm =
pos.prevLeafs.firstOrNull {
it.isNotWhiteSpace() &&
it.elementType != SqlTypes.DOT &&
it !is PsiErrorElement
}
if (!pos.isNotWhiteSpace() && !isRightFactor(prevElm)) return
val originalPosition = parameters.originalPosition ?: return
val blockElements = getAccessElementTextBlocks(originalPosition)
generateCompletionList(
Expand All @@ -141,29 +126,14 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
}
}

/**
* Check to enable code completion even in the case of the right side
*/
private fun isRightFactor(prevElm: PsiElement?) =
(
prevElm is SqlElEqExpr ||
prevElm?.elementType == SqlTypes.EL_IDENTIFIER ||
prevElm is SqlElGeExpr ||
prevElm is SqlElGtExpr ||
prevElm is SqlElLeExpr ||
prevElm is SqlElLtExpr ||
prevElm is SqlElNeExpr ||
prevElm is SqlElOrExpr ||
prevElm is SqlElAndExpr ||
prevElm?.elementType == SqlTypes.EL_PLUS ||
prevElm?.elementType == SqlTypes.EL_MINUS ||
prevElm?.elementType == SqlTypes.ASTERISK ||
prevElm?.elementType == SqlTypes.SLASH ||
prevElm?.elementType == SqlTypes.EL_PERCENT ||
prevElm?.isNotWhiteSpace() == true
)

private fun getAccessElementTextBlocks(targetElement: PsiElement): List<PsiElement> {
if (PsiTreeUtil.prevLeaf(targetElement)?.elementType != SqlTypes.EL_IDENTIFIER &&
targetElement.elementType != SqlTypes.EL_IDENTIFIER &&
PsiTreeUtil.prevLeaf(targetElement)?.elementType != SqlTypes.DOT
) {
return emptyList()
}

var blocks: List<PsiElement> = emptyList()
// If the immediate parent is a for, if, elseif directive,
// get the field access element list from its own forward element.
Expand All @@ -176,8 +146,7 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
parent is SqlElIfDirective ||
parent is SqlElElseifDirective
) {
val prevElms =
targetElement.findSelfBlocks()
val prevElms = findSelfBlocks(targetElement)
if (prevElms.isNotEmpty()) {
return prevElms
}
Expand Down Expand Up @@ -258,8 +227,7 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
// If the element has no parent-child relationship,
// create a list that also adds itself at the end.
if (blocks.isEmpty()) {
val prevElms =
targetElement.findSelfBlocks()
val prevElms = findSelfBlocks(targetElement)
if (prevElms.isNotEmpty()) {
blocks = prevElms
}
Expand Down Expand Up @@ -517,4 +485,45 @@ class SqlParameterCompletionProvider : CompletionProvider<CompletionParameters>(
// When you enter here, it is the top element, so return static fields and methods.
setFieldsAndMethodsCompletionResultSet(caretNextText, matchFields, matchMethod, result)
}

// Get the list of elements before itself
private fun findSelfBlocks(targetElement: PsiElement): List<PsiElement> {
val elms =
targetElement.prevLeafs
.takeWhile {
it.elementType != SqlTypes.BLOCK_COMMENT_START &&
!isSqlElSymbol(it) &&
it.elementType != SqlTypes.AT_SIGN &&
(
it.elementType != SqlTypes.LEFT_PAREN ||
it.parent.elementType == SqlTypes.EL_PARAMETERS
)
}.toList()
.plus(targetElement)
.filter {
it is PsiErrorElement ||
it is SqlElIdExpr ||
it.elementType == SqlTypes.EL_IDENTIFIER
}.filter {
it.isNotWhiteSpace() &&
PsiTreeUtil.getParentOfType(it, SqlElParameters::class.java) == null
}.sortedBy { it.textOffset }

return if (elms.isNotEmpty()) elms else emptyList()
}

private fun isSqlElSymbol(element: PsiElement): Boolean =
element.elementType == SqlTypes.EL_PLUS ||
element.elementType == SqlTypes.EL_MINUS ||
element.elementType == SqlTypes.ASTERISK ||
element.elementType == SqlTypes.EL_DIVIDE_EXPR ||
element.elementType == SqlTypes.EL_EQ ||
element.elementType == SqlTypes.EL_NE ||
element.elementType == SqlTypes.EL_LE_EXPR ||
element.elementType == SqlTypes.EL_LT_EXPR ||
element.elementType == SqlTypes.EL_GE_EXPR ||
element.elementType == SqlTypes.EL_GT_EXPR ||
element.elementType == SqlTypes.EL_AND ||
element.elementType == SqlTypes.EL_NOT ||
element.elementType == SqlTypes.SEPARATOR
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,14 @@ package org.domaframework.doma.intellij.extension.psi

import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.tree.IElementType
import com.intellij.psi.util.elementType
import com.intellij.psi.util.prevLeafs
import org.domaframework.doma.intellij.psi.SqlElIdExpr
import org.domaframework.doma.intellij.psi.SqlTypes

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

// Get the list of elements before itself
fun PsiElement.findSelfBlocks(): List<PsiElement> {
val elms =
this.prevLeafs
.takeWhile {
it.isNotWhiteSpace() &&
it.elementType != SqlTypes.AT_SIGN &&
(it.elementType != SqlTypes.LEFT_PAREN || it.parent.elementType == SqlTypes.EL_PARAMETERS) &&
it.elementType != SqlTypes.COMMA
}.toList()
.plus(this)
.filter { it is PsiErrorElement || it is SqlElIdExpr || it.elementType == SqlTypes.EL_IDENTIFIER }
.filter { it.isNotWhiteSpace() }
.sortedBy { it.textOffset }

return if (elms.isNotEmpty()) elms else emptyList()
}

/**
* Traverse a node's parent hierarchy
* to find the parent of the specified element type up to the comment block element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,28 @@ class SqlCompleteTest : DomaSqlTest() {
addSqlFile(
"$testDaoName/completeDaoArgument.sql",
"$testDaoName/completeInstancePropertyFromDaoArgumentClass.sql",
"$testDaoName/completeInstancePropertyWithMethodParameter.sql",
"$testDaoName/completeJavaPackageClass.sql",
"$testDaoName/completeDirective.sql",
"$testDaoName/completeBatchInsert.sql",
"$testDaoName/completeStaticPropertyFromStaticPropertyCall.sql",
"$testDaoName/completePropertyAfterStaticPropertyCall.sql",
"$testDaoName/completePropertyAfterStaticPropertyCallWithMethodParameter.sql",
"$testDaoName/completePropertyAfterStaticMethodCall.sql",
"$testDaoName/completeBuiltinFunction.sql",
"$testDaoName/completeDirectiveInsideIf.sql",
"$testDaoName/completeDirectiveFieldInsideIfWithMethodParameter.sql",
"$testDaoName/completeDirectiveInsideElseIf.sql",
"$testDaoName/completeDirectiveInsideFor.sql",
"$testDaoName/completeDirectiveInsideForWithMethodParameter.sql",
"$testDaoName/completeDirectiveFieldInsideIf.sql",
"$testDaoName/completeDirectiveFieldInsideElseIf.sql",
"$testDaoName/completeDirectiveFieldInsideFor.sql",
"$testDaoName/completeConcatenationOperator.sql",
"$testDaoName/completeComparisonOperator.sql",
"$testDaoName/completeParameterFirst.sql",
"$testDaoName/completeParameterFirstProperty.sql",
"$testDaoName/completeParameterFirstPropertyWithMethodParameter.sql",
"$testDaoName/completeParameterSecond.sql",
"$testDaoName/completeParameterSecondProperty.sql",
"$testDaoName/completeParameterFirstInStaticAccess.sql",
Expand Down Expand Up @@ -106,6 +111,26 @@ class SqlCompleteTest : DomaSqlTest() {
),
listOf("getEmployeeRank()"),
)
innerDirectiveCompleteTest(
"$testDaoName/completeInstancePropertyWithMethodParameter.sql",
listOf(
"byteValue()",
"compareTo()",
"doubleValue()",
"toString()",
),
listOf(
"employeeId",
"employeeName",
"department",
"rank",
"getFirstProject()",
"toLowerCase()",
"charAt()",
"contains()",
"isBlank()",
),
)
}

fun testCompleteJavaPackageClass() {
Expand Down Expand Up @@ -212,6 +237,28 @@ class SqlCompleteTest : DomaSqlTest() {
"addTermNumber()",
),
)

innerDirectiveCompleteTest(
"$testDaoName/completePropertyAfterStaticPropertyCallWithMethodParameter.sql",
listOf(
"projectId",
"projectNumber",
"projectName",
"projectCategory",
),
listOf(
"projectDetailId",
"members",
"manager",
"getFirstEmployee()",
"getTermNumber()",
"employeeId",
"projects",
"rank",
"contains()",
"isBlank()",
),
)
}

fun testCompleteCallStaticPropertyClassPackage() {
Expand Down Expand Up @@ -308,16 +355,30 @@ class SqlCompleteTest : DomaSqlTest() {
listOf("employee"),
listOf("project"),
)

innerDirectiveCompleteTest(
"$testDaoName/completeDirectiveFieldInsideIfWithMethodParameter.sql",
listOf("projectNumber", "projectCategory", "getFirstEmployee()", "getTermNumber()"),
listOf("project", "employee"),
)

innerDirectiveCompleteTest(
"$testDaoName/completeDirectiveInsideElseIf.sql",
listOf("employee", "project"),
emptyList(),
)

innerDirectiveCompleteTest(
"$testDaoName/completeDirectiveInsideFor.sql",
listOf("project"),
listOf("employee", "member", "%for"),
)

innerDirectiveCompleteTest(
"$testDaoName/completeDirectiveInsideForWithMethodParameter.sql",
listOf("clear()", "contains()", "get()", "getFirst()"),
listOf("projectNumber", "projectCategory", "getFirstEmployee()", "getTermNumber()"),
)
}

fun testCompleteDirectiveFieldInside() {
Expand Down Expand Up @@ -374,6 +435,12 @@ class SqlCompleteTest : DomaSqlTest() {
listOf("employee"),
)

innerDirectiveCompleteTest(
"$testDaoName/completeParameterFirstPropertyWithMethodParameter.sql",
listOf("projectNumber", "projectCategory", "getFirstEmployee()"),
listOf("employeeId", "employeeName", "getFirstProject()"),
)

innerDirectiveCompleteTest(
"$testDaoName/completeParameterSecond.sql",
listOf("employee"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ interface SqlCompleteTestDao {
@Select
Employee completeInstancePropertyFromDaoArgumentClass(Employee employee, String name);

@Select
Employee completeInstancePropertyWithMethodParameter(Employee employee, String name);

@Insert(sqlFile = true)
int completeJavaPackageClass(Employee employee);

Expand All @@ -34,6 +37,9 @@ interface SqlCompleteTestDao {
@Select
Project completePropertyAfterStaticPropertyCall();

@Select
Project completePropertyAfterStaticPropertyCallWithMethodParameter(Employee employee);

@Select
Project completePropertyAfterStaticMethodCall();

Expand All @@ -43,12 +49,18 @@ interface SqlCompleteTestDao {
@Update(sqlFile = true)
int completeDirectiveInsideIf(Employee employee,Project project);

@Update(sqlFile = true)
int completeDirectiveFieldInsideIfWithMethodParameter(Employee employee,Project project);

@Update(sqlFile = true)
int completeDirectiveInsideElseIf(Employee employee,Project project);

@Update(sqlFile = true)
int completeDirectiveInsideFor(Employee employee,Project project);

@Update(sqlFile = true)
int completeDirectiveInsideForWithMethodParameter(Employee employee,List<List<Project>> projectsList);

@Update(sqlFile = true)
int completeDirectiveFieldInsideIf(Employee employee,Project project);

Expand All @@ -70,6 +82,9 @@ interface SqlCompleteTestDao {
@Select
Employee completeParameterFirstProperty(Employee employee);

@Select
Employee completeParameterFirstPropertyWithMethodParameter(Employee employee, Integer index);

@Select
Employee completeParameterSecond(Employee employee);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class ProjectDetail {
public static Integr projectNumber;
private static String projectName;
private static String projectCategory;
private static List<Project> subProjects = new ArrayList<>();

private static Employee manager = new Employee();

Expand All @@ -44,4 +45,8 @@ public static String getCustomNumber(String prefix) {
return prefix + projectName;
}

public static Project getProject(String index){
return subProjects.get(Integer.parseInt(index));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
update employee e set
e.employee_name = /* employee.employeeName */'name'
, e.rank = /* employee.rank */1
where
e.employee_id = /* employee.employeeId */1
/*%if employee.getFirstProject(employee.employeeId).<caret> */
and e.department = /* employee.department */'department'
/*%elseif employee.department.startWith("100") */
and e.sub_department = /* employee.department */'department'
and e.rank >= /* employee.rank */9999
/*%else */
and e.sub_department = /* employee.department */'department'
/*%end*/
Loading
Loading