-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update rpc related IDE plugin checks
- Loading branch information
Showing
13 changed files
with
211 additions
and
118 deletions.
There are no files selected for viewing
6 changes: 1 addition & 5 deletions
6
harness/tests/src/main/kotlin/godot/tests/rpctests/RpcTests.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
...-intellij-plugin/src/main/kotlin/godot/intellij/plugin/annotator/function/RpcAnnotator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package godot.intellij.plugin.annotator.function | ||
|
||
import com.intellij.codeInspection.ProblemHighlightType | ||
import com.intellij.lang.annotation.AnnotationHolder | ||
import com.intellij.lang.annotation.Annotator | ||
import com.intellij.psi.PsiElement | ||
import godot.intellij.plugin.GodotPluginBundle | ||
import godot.intellij.plugin.data.model.RPC_ANNOTATION | ||
import godot.intellij.plugin.extension.isInGodotRoot | ||
import godot.intellij.plugin.extension.registerProblem | ||
import godot.intellij.plugin.quickfix.TransferModeIgnoresChannelQuickFix | ||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName | ||
import org.jetbrains.kotlin.idea.util.findAnnotation | ||
import org.jetbrains.kotlin.name.FqName | ||
import org.jetbrains.kotlin.nj2k.postProcessing.resolve | ||
import org.jetbrains.kotlin.psi.KtAnnotated | ||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression | ||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType | ||
|
||
class RpcAnnotator : Annotator { | ||
private val transferModeIgnoresChannelQuickFix by lazy { TransferModeIgnoresChannelQuickFix() } | ||
|
||
override fun annotate(element: PsiElement, holder: AnnotationHolder) { | ||
if (!element.isInGodotRoot()) return | ||
|
||
if (element is KtAnnotated && element.findAnnotation(FqName(RPC_ANNOTATION)) != null) { | ||
val valueArgumentList = element.findAnnotation(FqName(RPC_ANNOTATION))?.valueArgumentList ?: return | ||
|
||
val transferModeValueArgument = valueArgumentList | ||
.arguments | ||
.firstOrNull { it.isNamed() && it.getArgumentName()?.text == "transferMode" } // named; so position is not relevant | ||
?: valueArgumentList | ||
.arguments | ||
.getOrNull(2) // not named; so getting by argument position | ||
|
||
val isTransferModeUnreliableOrdered = transferModeValueArgument | ||
?.getArgumentExpression() | ||
?.getChildOfType<KtNameReferenceExpression>() | ||
?.resolve() | ||
?.getKotlinFqName() | ||
?.asString() == "godot.annotation.TransferMode.UNRELIABLE_ORDERED" | ||
|
||
val channelElement = valueArgumentList | ||
.arguments | ||
.firstOrNull { it.isNamed() && it.getArgumentName()?.text == "transferChannel" } // named; so position is not relevant | ||
?: valueArgumentList | ||
.arguments | ||
.getOrNull(3)// not named; so getting by argument position | ||
|
||
val channel = if (channelElement?.isNamed() == true) { | ||
channelElement.text.substringAfterLast("=").trim() | ||
} else { | ||
channelElement?.text | ||
} | ||
?.removeSurrounding("\"") | ||
?.toIntOrNull() ?: 0 | ||
|
||
if (channelElement != null && !isTransferModeUnreliableOrdered && channel != 0) { | ||
holder.registerProblem( | ||
message = GodotPluginBundle.message("problem.function.rpcChannelSetWhenTransferTypeIgnoresIt"), | ||
errorLocation = channelElement, | ||
quickFixes = arrayOf(transferModeIgnoresChannelQuickFix), | ||
problemHighlightType = ProblemHighlightType.WEAK_WARNING | ||
) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 0 additions & 79 deletions
79
...src/main/kotlin/godot/intellij/plugin/annotator/reference/RSetPropertyReferenceChecker.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +0,0 @@ | ||
package godot.intellij.plugin.annotator.reference | ||
|
||
import com.intellij.lang.annotation.AnnotationHolder | ||
import godot.intellij.plugin.GodotPluginBundle | ||
import godot.intellij.plugin.data.model.REGISTER_PROPERTY_ANNOTATION | ||
import godot.intellij.plugin.extension.registerProblem | ||
import godot.intellij.plugin.quickfix.TargetPropertyNotRegisteredQuickFix | ||
import org.jetbrains.kotlin.idea.base.utils.fqname.getKotlinFqName | ||
import org.jetbrains.kotlin.idea.util.findAnnotation | ||
import org.jetbrains.kotlin.name.FqName | ||
import org.jetbrains.kotlin.nj2k.postProcessing.resolve | ||
import org.jetbrains.kotlin.psi.KtCallExpression | ||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression | ||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression | ||
import org.jetbrains.kotlin.psi.KtNamedFunction | ||
import org.jetbrains.kotlin.psi.KtProperty | ||
import org.jetbrains.kotlin.psi.KtValueArgument | ||
import org.jetbrains.kotlin.psi.psiUtil.containingClass | ||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType | ||
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType | ||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull | ||
|
||
object RSetPropertyReferenceChecker { | ||
private val rsetFunctionNames = listOf( | ||
"rset", | ||
"rsetId", | ||
"rsetUnreliable", | ||
"rsetUnreliableId", | ||
) | ||
|
||
fun checkRpcTargetProperty(element: KtCallableReferenceExpression, holder: AnnotationHolder) { | ||
val relevantParent = element.parent.parent.parent | ||
val propertyReference = relevantParent.children.firstIsInstanceOrNull<KtNameReferenceExpression>() | ||
if ( | ||
relevantParent is KtCallExpression && | ||
rsetFunctionNames.contains(propertyReference?.text) && | ||
(propertyReference?.resolve() as? KtNamedFunction)?.containingClass()?.fqName?.asString() == "godot.Node" | ||
) { | ||
val targetProperty = element | ||
.callableReference | ||
.resolve() as? KtProperty | ||
|
||
val registerPropertyAnnotation = targetProperty?.findAnnotation(FqName(REGISTER_PROPERTY_ANNOTATION)) | ||
if (targetProperty != null && registerPropertyAnnotation == null) { | ||
holder.registerProblem( | ||
GodotPluginBundle.message("problem.rpc.calledPropertyNotRegistered"), | ||
element, | ||
TargetPropertyNotRegisteredQuickFix() | ||
) | ||
} else { | ||
if ( | ||
registerPropertyAnnotation?.valueArguments?.isEmpty() == true || | ||
registerPropertyAnnotation | ||
?.valueArgumentList | ||
?.getChildrenOfType<KtValueArgument>() | ||
?.mapNotNull { ktValueArgument -> | ||
ktValueArgument | ||
.getArgumentExpression() | ||
?.getChildOfType<KtNameReferenceExpression>() | ||
?.resolve() | ||
?.getKotlinFqName() | ||
?.asString() | ||
} | ||
?.filter { fqName -> | ||
fqName.startsWith("godot.MultiplayerAPI.RPCMode") | ||
} | ||
?.any { fqName -> | ||
fqName == "godot.MultiplayerAPI.RPCMode.DISABLED" | ||
} == true | ||
) { | ||
holder.registerProblem( | ||
GodotPluginBundle.message("problem.rpc.calledPropertyNotAccessible"), | ||
element | ||
) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
...rc/main/kotlin/godot/intellij/plugin/quickfix/TargetFunctionHasNoRpcAnnotationQuickFix.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package godot.intellij.plugin.quickfix | ||
|
||
import com.intellij.codeInspection.LocalQuickFix | ||
import com.intellij.codeInspection.ProblemDescriptor | ||
import com.intellij.openapi.project.Project | ||
import godot.intellij.plugin.GodotPluginBundle | ||
import godot.intellij.plugin.data.model.RPC_ANNOTATION | ||
import org.jetbrains.kotlin.idea.util.addAnnotation | ||
import org.jetbrains.kotlin.name.FqName | ||
import org.jetbrains.kotlin.nj2k.postProcessing.resolve | ||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression | ||
import org.jetbrains.kotlin.psi.KtNamedFunction | ||
|
||
class TargetFunctionHasNoRpcAnnotationQuickFix : LocalQuickFix { | ||
override fun getFamilyName(): String = GodotPluginBundle.message("quickFix.function.connectedFunctionHasNoRpcAnnotationRegistered.familyName") | ||
|
||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { | ||
val ktNamedFunction = (descriptor.psiElement as? KtCallableReferenceExpression) | ||
?.callableReference | ||
?.resolve() as? KtNamedFunction | ||
|
||
ktNamedFunction?.addAnnotation(FqName(RPC_ANNOTATION)) | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
...n/kotlin/godot/intellij/plugin/quickfix/TargetFunctionsRpcAnnotationHasRpcModeDisabled.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package godot.intellij.plugin.quickfix | ||
|
||
import com.intellij.codeInspection.LocalQuickFix | ||
import com.intellij.codeInspection.ProblemDescriptor | ||
import com.intellij.openapi.project.Project | ||
import godot.intellij.plugin.GodotPluginBundle | ||
import godot.intellij.plugin.data.model.RPC_ANNOTATION | ||
import org.jetbrains.kotlin.idea.util.findAnnotation | ||
import org.jetbrains.kotlin.name.FqName | ||
import org.jetbrains.kotlin.nj2k.postProcessing.resolve | ||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression | ||
import org.jetbrains.kotlin.psi.KtNamedFunction | ||
|
||
class TargetFunctionsRpcAnnotationHasRpcModeDisabled : LocalQuickFix { | ||
override fun getFamilyName(): String = GodotPluginBundle.message("quickFix.function.connectedFunctionsRpcAnnotationHasRpcModeDisabled.familyName") | ||
|
||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) { | ||
val ktNamedFunction = (descriptor.psiElement as? KtCallableReferenceExpression) | ||
?.callableReference | ||
?.resolve() as? KtNamedFunction | ||
|
||
val rpcAnnotationValueArgumentList = ktNamedFunction | ||
?.findAnnotation(FqName(RPC_ANNOTATION)) | ||
?.valueArgumentList | ||
|
||
val rpcModeValueArgument = rpcAnnotationValueArgumentList | ||
?.arguments | ||
?.firstOrNull { it.isNamed() && it.getArgumentName()?.text == "rpcMode" } // named; so position is not relevant | ||
?: rpcAnnotationValueArgumentList | ||
?.arguments | ||
?.getOrNull(0) // not named; so getting by argument position | ||
|
||
rpcModeValueArgument?.let { rpcAnnotationValueArgumentList?.removeArgument(it) } | ||
} | ||
} |
Oops, something went wrong.