Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e853496
Add SQL function call parameter inspection and validation
xterao Aug 15, 2025
8a2bb55
Enhance method checking for custom and built-in functions
xterao Aug 19, 2025
6760382
Use the shared routine that searches for methods with matching types …
xterao Sep 9, 2025
6a51508
Modify it to raise a type mismatch error for the first method invoked…
xterao Sep 9, 2025
c8fc2d2
Ensure type-matching method reference resolution for both instance me…
xterao Sep 9, 2025
76ccddd
Implement method parameter type checking for custom functions and bui…
xterao Sep 9, 2025
e097499
Refactor InspectionVisitorProcessor to remove shortName parameter and…
xterao Sep 9, 2025
ec0eb6d
Add .gitattributes to enforce LF line endings
xterao Aug 22, 2025
8ba3436
Refactor MethodParamContext and related classes for improved readabil…
xterao Sep 9, 2025
7fb6c16
Revise the error-highlighting conditions for custom functions.
xterao Sep 9, 2025
dddc02e
Refactor FieldMethodResolver to utilize MethodParamContext for parame…
xterao Sep 10, 2025
86ed8f5
Implement separate methods for retrieving custom function errors and …
xterao Sep 10, 2025
6134ca2
Enable retrieving the types of custom functions used within parameters.
xterao Sep 10, 2025
8a3241f
Fix the reference resolution so that methods used within parameters a…
xterao Sep 10, 2025
f01203f
Fix the code completion logic invoked after function parameters so it…
xterao Sep 10, 2025
9ee1fb7
Fix method matching to ensure parameter count matches before type com…
xterao Sep 10, 2025
a48cc76
Implement separately the logic for retrieving static method errors an…
xterao Sep 10, 2025
1baa06e
Refactor variable declarations to use 'val' for immutability in compl…
xterao Sep 10, 2025
b0cb24d
Add SQL files and update Doma configuration for method parameter vali…
xterao Sep 10, 2025
4c3e111
Update test to include hyperlink in documentation for invalid primary…
xterao Sep 11, 2025
ab6a352
Refactor SQL file handling in tests to use variable for file names
xterao Sep 11, 2025
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class ExpressionFunctionsHelper {
expressionClazz.superTypes.firstOrNull()?.canonicalText
?: expressionClazz.psiClassType.canonicalText
return project?.let {
expressionClazz.psiClassType.canonicalText
project
.getJavaClazz(parentType)
?.isInheritor(functionInterface, true) == true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright Doma Tools Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.domaframework.doma.intellij.common.psi

import com.intellij.psi.PsiTypes

class DummyPsiParentClass : PsiParentClass(PsiTypes.voidType())
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Doma Tools Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.domaframework.doma.intellij.common.psi

import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.domaframework.doma.intellij.psi.SqlElFunctionCallExpr
import org.domaframework.doma.intellij.psi.SqlElParameters

class MethodParamContext(
val methodIdExp: PsiElement,
val methodParams: SqlElParameters?,
) {
companion object {
fun of(method: PsiElement): MethodParamContext =
MethodParamContext(
setMethodIdExp(method),
setParameter(method),
)

private fun setParameter(method: PsiElement): SqlElParameters? =
if (method is SqlElFunctionCallExpr) {
method.elParameters
} else {
PsiTreeUtil.nextLeaf(method)?.parent as? SqlElParameters
}

private fun setMethodIdExp(method: PsiElement): PsiElement =
if (method is SqlElFunctionCallExpr) {
method.elIdExpr
} else {
method
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@
package org.domaframework.doma.intellij.common.psi

import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiField
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiType
import com.intellij.psi.util.PsiTypesUtil
import org.domaframework.doma.intellij.common.util.MethodMatcher
import org.domaframework.doma.intellij.extension.expr.extractParameterTypes

/**
* When parsing a field access element with SQL,
* manage the reference class information of the previous element
*/
class PsiParentClass(
open class PsiParentClass(
val type: PsiType,
) {
var clazz: PsiClass? = psiClass()
Expand Down Expand Up @@ -61,6 +65,34 @@ class PsiParentClass(
m.name.substringBefore("(") == methodName.substringBefore("(")
}

fun findMethod(
methodExpr: PsiElement,
shortName: String = "",
): MethodMatcher.MatchResult {
val context = MethodParamContext.of(methodExpr)
val methods = findMethods(context.methodIdExp.text)
if (context.methodParams == null) return MethodMatcher.MatchResult(validation = null)

val actualCount = context.methodParams.elExprList.size
val paramTypes = context.methodParams.extractParameterTypes(PsiManager.getInstance(methodExpr.project))
val matchResult =
MethodMatcher.findMatchingMethod(
context.methodIdExp,
methods,
paramTypes,
actualCount,
shortName,
)

return matchResult
}

fun findMethods(methodName: String): List<PsiMethod> =
getMethods()
?.filter { m ->
m.hasModifierProperty(PsiModifier.PUBLIC) && m.name.substringBefore("(") == methodName.substringBefore("(")
} ?: emptyList()

fun searchMethod(methodName: String): List<PsiMethod>? =
getMethods()?.filter { m ->
m.name.substringBefore("(").startsWith(methodName.substringBefore("(")) &&
Expand All @@ -81,4 +113,11 @@ class PsiParentClass(
m.hasModifierProperty(PsiModifier.PUBLIC) &&
m.name.substringBefore("(").startsWith(methodName.substringBefore("("))
}

fun findStaticMethods(methodName: String): List<PsiMethod> =
getMethods()
?.filter { m ->
m.hasModifierProperty(PsiModifier.STATIC) &&
m.hasModifierProperty(PsiModifier.PUBLIC) && m.name.substringBefore("(") == methodName.substringBefore("(")
} ?: emptyList()
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class FunctionCallCollector(
private val bind: String,
) : StaticDirectiveHandlerCollector() {
public override fun collect(): List<LookupElement>? {
var functions = mutableSetOf<PsiMethod>()
val functions = mutableSetOf<PsiMethod>()
val project = file?.project
val module = file?.module ?: return null
val isTest = CommonPathParameterUtil.isTest(module, file.virtualFile)
Expand All @@ -50,7 +50,10 @@ class FunctionCallCollector(
project?.let { ExpressionFunctionsHelper.setExpressionFunctionsInterface(it) }
?: return null

val expressionClazz = customFunctionClassName?.let { project.getJavaClazz(it) }
val expressionClazz =
customFunctionClassName?.let {
if (it.isNotEmpty()) project.getJavaClazz(it) else null
}
if (expressionClazz != null &&
ExpressionFunctionsHelper.isInheritor(expressionClazz)
) {
Expand All @@ -71,17 +74,17 @@ class FunctionCallCollector(
return functions
.filter {
it.name.startsWith(bind.substringAfter("@"))
}.map {
val parameters = it.parameterList.parameters.toList()
}.map { m ->
val parameters = m.parameterList.parameters.toList()
LookupElementBuilder
.create(createMethodLookupElement(caretNextText, it))
.withPresentableText(it.name)
.create(createMethodLookupElement(caretNextText, m))
.withPresentableText(m.name)
.withTailText(
"(${
parameters.joinToString(",") { "${it.type.presentableText} ${it.name}" }
parameters.joinToString(",") { p -> "${p.type.presentableText} ${p.name}" }
})",
true,
).withTypeText(it.returnType?.presentableText ?: "void")
).withTypeText(m.returnType?.presentableText ?: "void")
.withAutoCompletionPolicy(AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE)
}
}
Expand Down
Loading
Loading