diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt index f1d856c3148..5f4d456f71a 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt @@ -151,7 +151,7 @@ class BasicLookupElementFactory( val returnType = descriptor.getReturnType() element = element.withTypeText(if (returnType != null) DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(returnType) else "") - val insertsLambda = (insertHandler as KotlinFunctionInsertHandler).lambdaInfo != null + val insertsLambda = (insertHandler as? KotlinFunctionInsertHandler.Normal)?.lambdaInfo != null if (insertsLambda) { element = element.appendTailText(" {...} ", false) } @@ -211,7 +211,7 @@ class BasicLookupElementFactory( element = element.withStrikeoutness(true) } - if (insertHandler is KotlinFunctionInsertHandler && insertHandler.lambdaInfo != null) { + if ((insertHandler as? KotlinFunctionInsertHandler.Normal)?.lambdaInfo != null) { element.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, Unit) } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt index 53323c48d16..e5129972b35 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt @@ -39,25 +39,34 @@ class InsertHandlerProvider( return when (descriptor) { is FunctionDescriptor -> { - val needTypeArguments = needTypeArguments(descriptor) - val parameters = descriptor.valueParameters - when (parameters.size()) { - 0 -> KotlinFunctionInsertHandler(callType, needTypeArguments, inputValueArguments = false) + when (callType) { + is CallType.DEFAULT, is CallType.DOT, is CallType.SAFE -> { + val needTypeArguments = needTypeArguments(descriptor) + val parameters = descriptor.valueParameters + when (parameters.size()) { + 0 -> KotlinFunctionInsertHandler.Normal(needTypeArguments, inputValueArguments = false) - 1 -> { - val parameterType = parameters.single().getType() - if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) { - val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size() - if (parameterCount <= 1) { - // otherwise additional item with lambda template is to be added - return KotlinFunctionInsertHandler(callType, needTypeArguments, inputValueArguments = false, lambdaInfo = GenerateLambdaInfo(parameterType, false)) + 1 -> { + val parameterType = parameters.single().getType() + if (KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(parameterType)) { + val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size() + if (parameterCount <= 1) { + // otherwise additional item with lambda template is to be added + return KotlinFunctionInsertHandler.Normal(needTypeArguments, inputValueArguments = false, lambdaInfo = GenerateLambdaInfo(parameterType, false)) + } + } + KotlinFunctionInsertHandler.Normal(needTypeArguments, inputValueArguments = true) } + + else -> KotlinFunctionInsertHandler.Normal(needTypeArguments, inputValueArguments = true) } - KotlinFunctionInsertHandler(callType, needTypeArguments, inputValueArguments = true) } - else -> KotlinFunctionInsertHandler(callType, needTypeArguments, inputValueArguments = true) + is CallType.INFIX -> KotlinFunctionInsertHandler.Infix + + else -> KotlinFunctionInsertHandler.OnlyName } + } is PropertyDescriptor -> KotlinPropertyInsertHandler diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordCompletion.kt index fe1e22330fb..44b816fbec2 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordCompletion.kt @@ -29,7 +29,6 @@ import com.intellij.psi.filters.position.PositionElementFilter import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.KotlinKeywordInsertHandler -import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.lexer.JetKeywordToken import org.jetbrains.kotlin.lexer.JetTokens.* import org.jetbrains.kotlin.psi.* @@ -77,7 +76,7 @@ object KeywordCompletion { .withInsertHandler(if (keywordToken !in FUNCTION_KEYWORDS) KotlinKeywordInsertHandler else - KotlinFunctionInsertHandler(CallType.DEFAULT, inputTypeArguments = false, inputValueArguments = false)) + KotlinFunctionInsertHandler.Normal(inputTypeArguments = false, inputValueArguments = false)) consumer(element) } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt index 908468e1683..393392dbfa5 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt @@ -104,7 +104,7 @@ class LookupElementFactory( private fun createFunctionCallElementWithLambda(descriptor: FunctionDescriptor, parameterType: JetType, explicitLambdaParameters: Boolean, useReceiverTypes: Boolean): LookupElement { var lookupElement = createLookupElement(descriptor, useReceiverTypes) - val inputTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler).inputTypeArguments + val inputTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler.Normal).inputTypeArguments val lambdaInfo = GenerateLambdaInfo(parameterType, explicitLambdaParameters) val lambdaPresentation = lambdaPresentation(if (explicitLambdaParameters) parameterType else null) @@ -132,7 +132,7 @@ class LookupElementFactory( } override fun handleInsert(context: InsertionContext) { - KotlinFunctionInsertHandler(callType!!, inputTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this) + KotlinFunctionInsertHandler.Normal(inputTypeArguments, inputValueArguments = false, lambdaInfo = lambdaInfo).handleInsert(context, this) } } @@ -146,7 +146,7 @@ class LookupElementFactory( private fun createFunctionCallElementWithArgument(descriptor: FunctionDescriptor, argumentText: String, useReceiverTypes: Boolean): LookupElement { var lookupElement = createLookupElement(descriptor, useReceiverTypes) - val needTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler).inputTypeArguments + val needTypeArguments = (insertHandlerProvider.insertHandler(descriptor) as KotlinFunctionInsertHandler.Normal).inputTypeArguments lookupElement = FunctionCallWithArgumentLookupElement(lookupElement, descriptor, argumentText, needTypeArguments) if (isInStringTemplateAfterDollar) { @@ -175,7 +175,7 @@ class LookupElementFactory( } override fun handleInsert(context: InsertionContext) { - KotlinFunctionInsertHandler(callType!!, inputTypeArguments = needTypeArguments, inputValueArguments = false, argumentText = argumentText).handleInsert(context, this) + KotlinFunctionInsertHandler.Normal(inputTypeArguments = needTypeArguments, inputValueArguments = false, argumentText = argumentText).handleInsert(context, this) } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt index 4cf250b625a..93235a6378c 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt @@ -26,7 +26,6 @@ import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement import com.intellij.psi.codeStyle.CodeStyleSettingsManager import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings -import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.JetTypeArgumentList import org.jetbrains.kotlin.psi.psiUtil.endOffset @@ -34,153 +33,166 @@ import org.jetbrains.kotlin.types.JetType class GenerateLambdaInfo(val lambdaType: JetType, val explicitParameters: Boolean) -class KotlinFunctionInsertHandler( - val callType: CallType<*>, - val inputTypeArguments: Boolean, - val inputValueArguments: Boolean, - val argumentText: String = "", - val lambdaInfo: GenerateLambdaInfo? = null +sealed class KotlinFunctionInsertHandler( + ) : KotlinCallableInsertHandler() { - init { - if (lambdaInfo != null) { - assert(argumentText == "") + class Normal( + val inputTypeArguments: Boolean, + val inputValueArguments: Boolean, + val argumentText: String = "", + val lambdaInfo: GenerateLambdaInfo? = null + ) : KotlinFunctionInsertHandler() { + init { + if (lambdaInfo != null) { + assert(argumentText == "") + } } + + public override fun handleInsert(context: InsertionContext, item: LookupElement) { + super.handleInsert(context, item) + + val psiDocumentManager = PsiDocumentManager.getInstance(context.project) + psiDocumentManager.commitAllDocuments() + psiDocumentManager.doPostponedOperationsAndUnblockDocument(context.document) + + val startOffset = context.getStartOffset() + val element = context.getFile().findElementAt(startOffset) ?: return + + addArguments(context, element) + } + + private fun addArguments(context : InsertionContext, offsetElement : PsiElement) { + val completionChar = context.getCompletionChar() + if (completionChar == '(') { //TODO: more correct behavior related to braces type + context.setAddCompletionChar(false) + } + + var offset = context.tailOffset + val document = context.document + val editor = context.editor + val project = context.project + val chars = document.charsSequence + + val insertLambda = lambdaInfo != null && completionChar != '(' && !(completionChar == '\t' && chars.isCharAt(offset, '(')) + + val openingBracket = if (insertLambda) '{' else '(' + val closingBracket = if (insertLambda) '}' else ')' + + var insertTypeArguments = inputTypeArguments && (completionChar == '\n' || completionChar == '\r' || completionChar == Lookup.REPLACE_SELECT_CHAR) + + if (completionChar == Lookup.REPLACE_SELECT_CHAR) { + val offset1 = chars.skipSpaces(offset) + if (offset1 < chars.length()) { + if (chars[offset1] == '<') { + PsiDocumentManager.getInstance(project).commitDocument(document) + val token = context.getFile().findElementAt(offset1)!! + if (token.getNode().getElementType() == JetTokens.LT) { + val parent = token.getParent() + if (parent is JetTypeArgumentList && parent.getText().indexOf('\n') < 0/* if type argument list is on multiple lines this is more likely wrong parsing*/) { + offset = parent.endOffset + insertTypeArguments = false + } + } + } + } + } + + if (insertLambda && lambdaInfo!!.explicitParameters) { + insertTypeArguments = false + } + + if (insertTypeArguments) { + document.insertString(offset, "<>") + editor.caretModel.moveToOffset(offset + 1) + offset += 2 + } + + var openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset) + var closeBracketOffset = openingBracketOffset?.let { chars.indexOfSkippingSpace(closingBracket, it + 1) } + var inBracketsShift = 0 + + if (insertLambda && lambdaInfo!!.explicitParameters && closeBracketOffset == null) { + openingBracketOffset = null + } + + if (openingBracketOffset == null) { + if (insertLambda) { + if (completionChar == ' ' || completionChar == '{') { + context.setAddCompletionChar(false) + } + + if (isInsertSpacesInOneLineFunctionEnabled(project)) { + document.insertString(offset, " { }") + inBracketsShift = 1 + } + else { + document.insertString(offset, " {}") + } + } + else { + document.insertString(offset, "()") + } + PsiDocumentManager.getInstance(project).commitDocument(document) + + openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset)!! + closeBracketOffset = chars.indexOfSkippingSpace(closingBracket, openingBracketOffset + 1)!! + } + + if (insertLambda && lambdaInfo!!.explicitParameters) { + insertLambdaTemplate(context, TextRange(openingBracketOffset, closeBracketOffset!! + 1), lambdaInfo!!.lambdaType) + return + } + + document.insertString(openingBracketOffset + 1, argumentText) + if (closeBracketOffset != null) { + closeBracketOffset += argumentText.length() + } + + if (!insertTypeArguments) { + if (shouldPlaceCaretInBrackets(completionChar) || closeBracketOffset == null) { + editor.caretModel.moveToOffset(openingBracketOffset + 1 + inBracketsShift) + if (!insertLambda) { + AutoPopupController.getInstance(project)?.autoPopupParameterInfo(editor, offsetElement) + } + } + else { + editor.caretModel.moveToOffset(closeBracketOffset + 1) + } + } + } + + private fun shouldPlaceCaretInBrackets(completionChar: Char): Boolean { + if (completionChar == ',' || completionChar == '.' || completionChar == '=') return false + if (completionChar == '(') return true + return inputValueArguments || lambdaInfo != null + } + + private fun isInsertSpacesInOneLineFunctionEnabled(project: Project) + = CodeStyleSettingsManager.getSettings(project).getCustomSettings(javaClass())!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD } + object Infix : KotlinFunctionInsertHandler() { + public override fun handleInsert(context: InsertionContext, item: LookupElement) { + super.handleInsert(context, item) + + if (context.completionChar == ' ') { + context.setAddCompletionChar(false) + } + + val tailOffset = context.tailOffset + context.document.insertString(tailOffset, " ") + context.editor.caretModel.moveToOffset(tailOffset + 1) + } + } + + object OnlyName : KotlinFunctionInsertHandler() + public override fun handleInsert(context: InsertionContext, item: LookupElement) { super.handleInsert(context, item) val psiDocumentManager = PsiDocumentManager.getInstance(context.project) psiDocumentManager.commitAllDocuments() - psiDocumentManager.doPostponedOperationsAndUnblockDocument(context.getDocument()) - - val startOffset = context.getStartOffset() - val element = context.getFile().findElementAt(startOffset) ?: return - - when (callType) { - CallType.PACKAGE_DIRECTIVE, CallType.IMPORT_DIRECTIVE, CallType.CALLABLE_REFERENCE -> return - - CallType.INFIX -> { - if (context.getCompletionChar() == ' ') { - context.setAddCompletionChar(false) - } - - val tailOffset = context.getTailOffset() - context.getDocument().insertString(tailOffset, " ") - context.getEditor().getCaretModel().moveToOffset(tailOffset + 1) - } - - else -> addArguments(context, element) - } + psiDocumentManager.doPostponedOperationsAndUnblockDocument(context.document) } - - private fun addArguments(context : InsertionContext, offsetElement : PsiElement) { - val completionChar = context.getCompletionChar() - if (completionChar == '(') { //TODO: more correct behavior related to braces type - context.setAddCompletionChar(false) - } - - var offset = context.tailOffset - val document = context.document - val editor = context.editor - val project = context.project - val chars = document.charsSequence - - val insertLambda = lambdaInfo != null && completionChar != '(' && !(completionChar == '\t' && chars.isCharAt(offset, '(')) - - val openingBracket = if (insertLambda) '{' else '(' - val closingBracket = if (insertLambda) '}' else ')' - - var insertTypeArguments = inputTypeArguments && (completionChar == '\n' || completionChar == '\r' || completionChar == Lookup.REPLACE_SELECT_CHAR) - - if (completionChar == Lookup.REPLACE_SELECT_CHAR) { - val offset1 = chars.skipSpaces(offset) - if (offset1 < chars.length()) { - if (chars[offset1] == '<') { - PsiDocumentManager.getInstance(project).commitDocument(document) - val token = context.getFile().findElementAt(offset1)!! - if (token.getNode().getElementType() == JetTokens.LT) { - val parent = token.getParent() - if (parent is JetTypeArgumentList && parent.getText().indexOf('\n') < 0/* if type argument list is on multiple lines this is more likely wrong parsing*/) { - offset = parent.endOffset - insertTypeArguments = false - } - } - } - } - } - - if (insertLambda && lambdaInfo!!.explicitParameters) { - insertTypeArguments = false - } - - if (insertTypeArguments) { - document.insertString(offset, "<>") - editor.caretModel.moveToOffset(offset + 1) - offset += 2 - } - - var openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset) - var closeBracketOffset = openingBracketOffset?.let { chars.indexOfSkippingSpace(closingBracket, it + 1) } - var inBracketsShift = 0 - - if (insertLambda && lambdaInfo!!.explicitParameters && closeBracketOffset == null) { - openingBracketOffset = null - } - - if (openingBracketOffset == null) { - if (insertLambda) { - if (completionChar == ' ' || completionChar == '{') { - context.setAddCompletionChar(false) - } - - if (isInsertSpacesInOneLineFunctionEnabled(project)) { - document.insertString(offset, " { }") - inBracketsShift = 1 - } - else { - document.insertString(offset, " {}") - } - } - else { - document.insertString(offset, "()") - } - PsiDocumentManager.getInstance(project).commitDocument(document) - - openingBracketOffset = chars.indexOfSkippingSpace(openingBracket, offset)!! - closeBracketOffset = chars.indexOfSkippingSpace(closingBracket, openingBracketOffset + 1)!! - } - - if (insertLambda && lambdaInfo!!.explicitParameters) { - insertLambdaTemplate(context, TextRange(openingBracketOffset, closeBracketOffset!! + 1), lambdaInfo!!.lambdaType) - return - } - - document.insertString(openingBracketOffset + 1, argumentText) - if (closeBracketOffset != null) { - closeBracketOffset += argumentText.length() - } - - if (!insertTypeArguments) { - if (shouldPlaceCaretInBrackets(completionChar) || closeBracketOffset == null) { - editor.caretModel.moveToOffset(openingBracketOffset + 1 + inBracketsShift) - if (!insertLambda) { - AutoPopupController.getInstance(project)?.autoPopupParameterInfo(editor, offsetElement) - } - } - else { - editor.caretModel.moveToOffset(closeBracketOffset + 1) - } - } - } - - private fun shouldPlaceCaretInBrackets(completionChar: Char): Boolean { - if (completionChar == ',' || completionChar == '.' || completionChar == '=') return false - if (completionChar == '(') return true - return inputValueArguments || lambdaInfo != null - } - - private fun isInsertSpacesInOneLineFunctionEnabled(project: Project) - = CodeStyleSettingsManager.getSettings(project).getCustomSettings(javaClass())!!.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD } \ No newline at end of file diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt index b0bb53f2385..3f79d482cfe 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt @@ -34,7 +34,6 @@ import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler import org.jetbrains.kotlin.idea.core.psiClassToDescriptor import org.jetbrains.kotlin.idea.resolve.ResolutionFacade -import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.idea.util.FuzzyType import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.makeNotNullable @@ -204,9 +203,9 @@ class TypeInstantiationItems( } val baseInsertHandler = when (visibleConstructors.size()) { - 0 -> KotlinFunctionInsertHandler(CallType.DEFAULT, inputTypeArguments = false, inputValueArguments = false) - 1 -> lookupElementFactory.insertHandlerProvider.insertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler - else -> KotlinFunctionInsertHandler(CallType.DEFAULT, inputTypeArguments = false, inputValueArguments = true) + 0 -> KotlinFunctionInsertHandler.Normal(inputTypeArguments = false, inputValueArguments = false) + 1 -> lookupElementFactory.insertHandlerProvider.insertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler.Normal + else -> KotlinFunctionInsertHandler.Normal(inputTypeArguments = false, inputValueArguments = true) } insertHandler = object : InsertHandler { diff --git a/idea/idea-completion/testData/basic/common/callableReference/EmptyQualifier.kt b/idea/idea-completion/testData/basic/common/callableReference/EmptyQualifier.kt index 6af3f580377..89ecb10fc86 100644 --- a/idea/idea-completion/testData/basic/common/callableReference/EmptyQualifier.kt +++ b/idea/idea-completion/testData/basic/common/callableReference/EmptyQualifier.kt @@ -12,6 +12,8 @@ class C { val memberVal = 1 + fun funWithFunctionParameter(p: () -> Unit) {} + class NestedClass inner class InnerClass @@ -48,3 +50,4 @@ abstract class AbstractClass // ABSENT: AbstractClass // ABSENT: class // ABSENT: class.java +// EXIST: { itemText: "funWithFunctionParameter", tailText: "(p: () -> Unit)", attributes: "bold" } diff --git a/idea/idea-completion/testData/basic/multifile/InImport/InImport.dependency.kt b/idea/idea-completion/testData/basic/multifile/InImport/InImport.dependency.kt index 9c493558d44..aedfea96b0b 100644 --- a/idea/idea-completion/testData/basic/multifile/InImport/InImport.dependency.kt +++ b/idea/idea-completion/testData/basic/multifile/InImport/InImport.dependency.kt @@ -3,5 +3,7 @@ package second fun String.extensionFun(){} val Int.extensionVal: Int get() = 1 -fun topLevelFun(p: (String, Int) -> Unit){} +fun topLevelFun1(p: (String, Int) -> Unit){} +fun topLevelFun2(p: () -> Unit){} val topLevelVal: Int = 1 + diff --git a/idea/idea-completion/testData/basic/multifile/InImport/InImport.kt b/idea/idea-completion/testData/basic/multifile/InImport/InImport.kt index 97bf17fd056..1acf4d0a9aa 100644 --- a/idea/idea-completion/testData/basic/multifile/InImport/InImport.kt +++ b/idea/idea-completion/testData/basic/multifile/InImport/InImport.kt @@ -4,5 +4,7 @@ import second. // EXIST: { itemText: "extensionFun", tailText: "() for String in second", attributes: "" } // EXIST: { itemText: "extensionVal", tailText: " for Int in second", attributes: "" } -// EXIST: { itemText: "topLevelFun", tailText: "(p: (String, Int) -> Unit) (second)", attributes: "" } +// EXIST: { itemText: "topLevelFun1", tailText: "(p: (String, Int) -> Unit) (second)", attributes: "" } +// EXIST: { itemText: "topLevelFun2", tailText: "(p: () -> Unit) (second)", attributes: "" } // EXIST: { itemText: "topLevelVal", tailText: " (second)", attributes: "" } +// NOTHING_ELSE \ No newline at end of file