fun printPattern()

in src/main/kotlin/org/arend/refactoring/changeSignature/ArendChangeSignatureUtils.kt [254:317]


fun printPattern(pattern: Concrete.Pattern, psiElement: ArendPattern, refactoringContext: ChangeSignatureRefactoringContext): IntermediatePrintResult {
    val isInsideAppExprLeaf = !(pattern.data == psiElement ||
            (pattern.data as? ArendPattern)?.let{ it.constructorReference != null && it.parent == psiElement } == true)

    if (pattern is Concrete.ConstructorPattern && !isInsideAppExprLeaf) {
        val constructor = (pattern.constructor as DataLocatedReferable).data?.element
        val constructorIsInfix = constructor is GlobalReferable && constructor.precedence.isInfix
        val asTextWithWhitespace = (psiElement.asPattern?.getWhitespace(SpaceDirection.LeadingSpace) ?: "") + (psiElement.asPattern?.text ?: "")
        val descriptor = if (constructor is Referable) refactoringContext.identifyDescriptor(constructor) else null
        val patternEntry = PatternEntry(refactoringContext, psiElement, descriptor, pattern)

        return if (descriptor != null) {
            val processResult = patternEntry.printUsageEntry(constructor as? GlobalReferable)
            val baseText = processResult.text + asTextWithWhitespace
            IntermediatePrintResult(baseText, processResult.parenthesizedPrefixText,
                isAtomic = false,
                isLambda = false,
                referable = constructor as? GlobalReferable
            )
        } else {
            val builder = StringBuilder()
            var explicitArgCount = 0
            val processedFunction = refactoringContext.textGetter(pattern.constructorData as ArendPattern)
            val (strippedFunc, isAtomic) = if (patternEntry.blocks.size == 1 && patternEntry.blocks[0] == FUNCTION_INDEX) getStrippedPsi(pattern.data as PsiElement) else Pair(null, false)
            val strippedText = strippedFunc?.let { refactoringContext.textGetter(it) }

            for (block in patternEntry.blocks) when (block) {
                is Int -> if (block == FUNCTION_INDEX) builder.append(processedFunction) else patternEntry.getArguments()[block].let {
                    if (it.isExplicit) explicitArgCount++
                    val textInBrackets = "{${it.printResult.text}}"
                    val text = if (it.isExplicit) (if (explicitArgCount == 2 && constructorIsInfix && it.printResult.parenthesizedPrefixText != null) it.printResult.parenthesizedPrefixText else it.printResult.text) else textInBrackets
                    builder.append(text)
                }
                is PsiElement -> builder.append(refactoringContext.textGetter(block))
            }
            IntermediatePrintResult(strippedText ?: builder.toString().let { if (isAtomic && constructorIsInfix) "($it)" else it}, null, isAtomic, false, constructor as? GlobalReferable
            )
        }
    }

    fun textGetterForPatterns(exprData: PsiElement, preferStrippedVersion: Boolean): String {
        val replacementTextEntry = refactoringContext.textReplacements[exprData]
        if (replacementTextEntry != null) {
            if (!preferStrippedVersion && exprData is ArendPattern && !exprData.isExplicit) return "{$replacementTextEntry}"
            return replacementTextEntry
        }
        if (exprData.firstChild == null) return exprData.text
        val childRange = if (exprData is ArendPattern && !exprData.isExplicit) {
            val lbrace = exprData.childrenWithLeaves.indexOfFirst { it.elementType == LBRACE }
            val rbrace = exprData.childrenWithLeaves.indexOfFirst { it.elementType == RBRACE }
            if (lbrace == -1 || rbrace == -1 || lbrace - 1 > rbrace)
                exprData.childrenWithLeaves.toList() else
                exprData.childrenWithLeaves.toList().subList(lbrace + 1, rbrace)
        } else exprData.childrenWithLeaves.toList()

        return buildString {
            for (c in childRange)
                append(textGetterForPatterns(c, false))
        }
    }

    val (exprData, isAtomic) = getStrippedPsi(pattern.data as PsiElement)
    return IntermediatePrintResult(textGetterForPatterns(exprData, true), null, isAtomic, false, null)
}