in src/org/jetbrains/r/refactoring/inline/RInlineAssignmentHandler.kt [46:103]
override fun inlineElement(project: Project, editor: Editor?, psiElement: PsiElement) {
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, psiElement)) return
if (PsiTreeUtil.hasErrorElements(psiElement)) RInlineUtil.showErrorAndExit(project, editor, RBundle.message(
"inline.assignment.handler.error.rule.with.errors.description")) { return }
val targetElement = if (editor != null) TargetElementUtil.findTargetElement(editor, TargetElementUtil.getInstance().getAllAccepted()) else null
if (targetElement is RIdentifierExpression && RPsiUtil.isNamedArgument(targetElement)) return
if (ReferencesSearch.search(psiElement, LocalSearchScope(RRefactoringUtil.getRScope(psiElement))).findFirst() == null) {
RInlineUtil.showErrorAndExit(project, editor, RBundle.message(
"inline.assignment.handler.error.rule.never.used.description")) { return }
}
// needed to allow for for current caret element only inlining
var reference = if (editor != null) TargetElementUtil.findReference(editor) else null
if (reference != null && reference.element.parent != psiElement) {
val targets = (reference as RReferenceBase<*>).multiResolve(false).map { it.element }
if (psiElement !in targets) reference = null
}
val assignmentStatement = psiElement as? RAssignmentStatement ?: psiElement.parent as RAssignmentStatement
val name = assignmentStatement.name
val controlFlow = RRefactoringUtil.getRScope(assignmentStatement).controlFlow
val lastDefs = RInlineUtil.getLatestDefs(controlFlow, name, reference?.element)
if (lastDefs.size > 1) RInlineUtil.showErrorAndExit(project, editor, RBundle.message(
"inline.assignment.handler.error.no.dominating.definition")) { return }
val realAssignmentStatement = lastDefs.firstOrNull() as? RAssignmentStatement ?: assignmentStatement
var refElement = reference?.element as? RIdentifierExpression
// To prevent inlining left part of assignments
if (refElement == (refElement?.parent as? RAssignmentStatement)?.assignee) {
refElement = null
}
val isFunction = realAssignmentStatement.isFunctionDeclaration
if (isFunction) {
val errorMessage = when {
hasFunctionInside(realAssignmentStatement) -> RBundle.message("inline.assignment.handler.error.fun.in.fun")
hasRecursiveCall(realAssignmentStatement) -> RBundle.message("inline.assignment.handler.error.fun.self.ref")
hasInterruptIfs(project, realAssignmentStatement) -> RBundle.message("inline.assignment.handler.error.interrupts.flow")
hasUseMethod(realAssignmentStatement) -> RBundle.message("inline.assignment.handler.error.has.use.method")
else -> null
}
if (errorMessage != null) {
RInlineUtil.showErrorAndExit(project, editor, errorMessage) { return }
}
}
if (ApplicationManager.getApplication().isUnitTestMode) {
RInlineAssignmentProcessor(project, editor, realAssignmentStatement, refElement, inlineThisOnly, isFunction, removeDefinition).run()
}
else {
RInlineAssignmentDialog(project, editor, isFunction, realAssignmentStatement, refElement).show()
}
}