diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/unwrap/KotlinUnwrapRemoveBase.java b/idea/src/org/jetbrains/kotlin/idea/codeInsight/unwrap/KotlinUnwrapRemoveBase.java index 365fab1eac2..87393706ce6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/unwrap/KotlinUnwrapRemoveBase.java +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/unwrap/KotlinUnwrapRemoveBase.java @@ -44,7 +44,7 @@ public abstract class KotlinUnwrapRemoveBase extends AbstractUnwrapper$s" else s } - @NotNull - public static String wrapOrSkip(@NotNull String s, boolean inCode) { - return inCode ? "" + s + "" : s; + fun formatClassDescriptor(classDescriptor: DeclarationDescriptor): String { + return IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor) } - @NotNull - public static String formatClassDescriptor(@NotNull DeclarationDescriptor classDescriptor) { - return IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor); - } + fun formatPsiClass( + psiClass: PsiClass, + markAsJava: Boolean, + inCode: Boolean): String { + var description: String - @NotNull - public static String formatPsiClass( - @NotNull PsiClass psiClass, - boolean markAsJava, - boolean inCode - ) { - String description; - - String kind = psiClass.isInterface() ? "interface " : "class "; + val kind = if (psiClass.isInterface) "interface " else "class " description = kind + PsiFormatUtil.formatClass( psiClass, - PsiFormatUtilBase.SHOW_CONTAINING_CLASS - | PsiFormatUtilBase.SHOW_NAME - | PsiFormatUtilBase.SHOW_PARAMETERS - | PsiFormatUtilBase.SHOW_TYPE - ); - description = wrapOrSkip(description, inCode); + PsiFormatUtilBase.SHOW_CONTAINING_CLASS or PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE) + description = wrapOrSkip(description, inCode) - return markAsJava ? "[Java] " + description : description; + return if (markAsJava) "[Java] " + description else description } - @NotNull - public static List checkSuperMethods( - @NotNull KtDeclaration declaration, - @Nullable Collection ignore, - @NotNull String actionStringKey - ) { - BindingContext bindingContext = ResolutionUtils.analyze(declaration, BodyResolveMode.FULL); + fun checkSuperMethods( + declaration: KtDeclaration, + ignore: Collection?, + actionStringKey: String): List { + val bindingContext = declaration.analyze(BodyResolveMode.FULL) - CallableDescriptor declarationDescriptor = - (CallableDescriptor)bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); + val declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration) as CallableDescriptor? - if (declarationDescriptor == null || declarationDescriptor instanceof LocalVariableDescriptor) { - return Collections.singletonList(declaration); + if (declarationDescriptor == null || declarationDescriptor is LocalVariableDescriptor) { + return listOf(declaration) } - Project project = declaration.getProject(); - Map overriddenElementsToDescriptor = new HashMap(); - for (CallableDescriptor overriddenDescriptor : DescriptorUtils.getAllOverriddenDescriptors(declarationDescriptor)) { - PsiElement overriddenDeclaration = DescriptorToSourceUtilsIde.INSTANCE.getAnyDeclaration(project, overriddenDescriptor); - if (PsiTreeUtil.instanceOf(overriddenDeclaration, KtNamedFunction.class, KtProperty.class, PsiMethod.class)) { - overriddenElementsToDescriptor.put(overriddenDeclaration, overriddenDescriptor); + val project = declaration.project + val overriddenElementsToDescriptor = HashMap() + for (overriddenDescriptor in DescriptorUtils.getAllOverriddenDescriptors(declarationDescriptor)) { + val overriddenDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, overriddenDescriptor) ?: continue + if (PsiTreeUtil.instanceOf(overriddenDeclaration, KtNamedFunction::class.java, KtProperty::class.java, PsiMethod::class.java)) { + overriddenElementsToDescriptor.put(overriddenDeclaration, overriddenDescriptor) } } if (ignore != null) { - overriddenElementsToDescriptor.keySet().removeAll(ignore); + overriddenElementsToDescriptor.keys.removeAll(ignore) } - if (overriddenElementsToDescriptor.isEmpty()) return Collections.singletonList(declaration); + if (overriddenElementsToDescriptor.isEmpty()) return listOf(declaration) - List superClasses = getClassDescriptions(overriddenElementsToDescriptor); - return askUserForMethodsToSearch(declaration, declarationDescriptor, overriddenElementsToDescriptor, superClasses, actionStringKey); + val superClasses = getClassDescriptions(overriddenElementsToDescriptor) + return askUserForMethodsToSearch(declaration, declarationDescriptor, overriddenElementsToDescriptor, superClasses, actionStringKey) } - @NotNull - private static List askUserForMethodsToSearch( - @NotNull KtDeclaration declaration, - @NotNull CallableDescriptor declarationDescriptor, - @NotNull Map overriddenElementsToDescriptor, - @NotNull List superClasses, - @NotNull String actionStringKey - ) { - if (ApplicationManager.getApplication().isUnitTestMode()) { - return ContainerUtil.newArrayList(overriddenElementsToDescriptor.keySet()); + private fun askUserForMethodsToSearch( + declaration: KtDeclaration, + declarationDescriptor: CallableDescriptor, + overriddenElementsToDescriptor: Map, + superClasses: List, + actionStringKey: String): List { + if (ApplicationManager.getApplication().isUnitTestMode) { + return ContainerUtil.newArrayList(overriddenElementsToDescriptor.keys) } - String superClassesStr = "\n" + StringUtil.join(superClasses, ""); - String message = KotlinBundle.message( + val superClassesStr = "\n" + StringUtil.join(superClasses, "") + val message = KotlinBundle.message( "x.overrides.y.in.class.list", DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(declarationDescriptor), superClassesStr, - KotlinBundle.message(actionStringKey) - ); + KotlinBundle.message(actionStringKey)) - int exitCode = Messages.showYesNoCancelDialog(declaration.getProject(), message, IdeBundle.message("title.warning"), Messages.getQuestionIcon()); - switch (exitCode) { - case Messages.YES: - return ContainerUtil.newArrayList(overriddenElementsToDescriptor.keySet()); - case Messages.NO: - return Collections.singletonList(declaration); - default: - return Collections.emptyList(); + val exitCode = Messages.showYesNoCancelDialog(declaration.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon()) + when (exitCode) { + Messages.YES -> return ContainerUtil.newArrayList(overriddenElementsToDescriptor.keys) + Messages.NO -> return listOf(declaration) + else -> return emptyList() } } - @NotNull - private static List getClassDescriptions(@NotNull Map overriddenElementsToDescriptor) { - return ContainerUtil.map( - overriddenElementsToDescriptor.entrySet(), - new Function, String>() { - @Override - public String fun(Map.Entry entry) { - String description; + private fun getClassDescriptions(overriddenElementsToDescriptor: Map): List { + return overriddenElementsToDescriptor.entries.map { entry -> + val description: String - PsiElement element = entry.getKey(); - CallableDescriptor descriptor = entry.getValue(); - if (element instanceof KtNamedFunction || element instanceof KtProperty) { - description = formatClassDescriptor(descriptor.getContainingDeclaration()); - } - else { - assert element instanceof PsiMethod : "Invalid element: " + element.getText(); - - PsiClass psiClass = ((PsiMethod) element).getContainingClass(); - assert psiClass != null : "Invalid element: " + element.getText(); - - description = formatPsiClass(psiClass, true, false); - } - - return " " + description + "\n"; - } - } - ); - } - - @NotNull - public static String formatClass(@NotNull DeclarationDescriptor classDescriptor, boolean inCode) { - PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor); - if (element instanceof PsiClass) { - return formatPsiClass((PsiClass) element, false, inCode); - } - - return wrapOrSkip(formatClassDescriptor(classDescriptor), inCode); - } - - @NotNull - public static String formatFunction(@NotNull DeclarationDescriptor functionDescriptor, boolean inCode) { - PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor); - if (element instanceof PsiMethod) { - return formatPsiMethod((PsiMethod) element, false, inCode); - } - - return wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode); - } - - @NotNull - private static String formatFunctionDescriptor(@NotNull DeclarationDescriptor functionDescriptor) { - return DescriptorRenderer.COMPACT.render(functionDescriptor); - } - - @NotNull - public static String formatPsiMethod( - @NotNull PsiMethod psiMethod, - boolean showContainingClass, - boolean inCode) { - int options = PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS | PsiFormatUtilBase.SHOW_TYPE; - if (showContainingClass) { - //noinspection ConstantConditions - options |= PsiFormatUtilBase.SHOW_CONTAINING_CLASS; - } - - String description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE); - description = wrapOrSkip(description, inCode); - - return "[Java] " + description; - } - - @NotNull - public static String formatJavaOrLightMethod(@NotNull PsiMethod method) { - PsiElement originalDeclaration = LightClassUtilsKt.getUnwrapped(method); - if (originalDeclaration instanceof KtDeclaration) { - KtDeclaration ktDeclaration = (KtDeclaration) originalDeclaration; - BindingContext bindingContext = ResolutionUtils.analyze(ktDeclaration, BodyResolveMode.FULL); - DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, ktDeclaration); - - if (descriptor != null) return formatFunctionDescriptor(descriptor); - } - return formatPsiMethod(method, false, false); - } - - @NotNull - public static String formatClass(@NotNull KtClassOrObject classOrObject) { - BindingContext bindingContext = ResolutionUtils.analyze(classOrObject, BodyResolveMode.FULL); - DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); - - if (descriptor instanceof ClassDescriptor) return formatClassDescriptor(descriptor); - return "class " + classOrObject.getName(); - } - - @Nullable - public static Collection checkParametersInMethodHierarchy(@NotNull PsiParameter parameter) { - PsiMethod method = (PsiMethod)parameter.getDeclarationScope(); - - Set parametersToDelete = collectParametersHierarchy(method, parameter); - if (parametersToDelete.size() > 1) { - if (ApplicationManager.getApplication().isUnitTestMode()) { - return parametersToDelete; - } - - String message = - KotlinBundle.message("delete.param.in.method.hierarchy", formatJavaOrLightMethod(method)); - int exitCode = Messages.showOkCancelDialog( - parameter.getProject(), message, IdeBundle.message("title.warning"), Messages.getQuestionIcon() - ); - if (exitCode == Messages.OK) { - return parametersToDelete; + val element = entry.key + val descriptor = entry.value + if (element is KtNamedFunction || element is KtProperty) { + description = formatClassDescriptor(descriptor.getContainingDeclaration()) } else { - return null; + assert(element is PsiMethod) { "Invalid element: " + element.getText() } + + val psiClass = (element as PsiMethod).containingClass ?: error("Invalid element: " + element.getText()) + + description = formatPsiClass(psiClass, true, false) + } + + " " + description + "\n" + } + } + + fun formatClass(classDescriptor: DeclarationDescriptor, inCode: Boolean): String { + val element = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor) + if (element is PsiClass) { + return formatPsiClass((element as PsiClass?)!!, false, inCode) + } + + return wrapOrSkip(formatClassDescriptor(classDescriptor), inCode) + } + + fun formatFunction(functionDescriptor: DeclarationDescriptor, inCode: Boolean): String { + val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor) + if (element is PsiMethod) { + return formatPsiMethod((element as PsiMethod?)!!, false, inCode) + } + + return wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode) + } + + private fun formatFunctionDescriptor(functionDescriptor: DeclarationDescriptor): String { + return DescriptorRenderer.COMPACT.render(functionDescriptor) + } + + fun formatPsiMethod( + psiMethod: PsiMethod, + showContainingClass: Boolean, + inCode: Boolean): String { + var options = PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE + if (showContainingClass) { + //noinspection ConstantConditions + options = options or PsiFormatUtilBase.SHOW_CONTAINING_CLASS + } + + var description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE) + description = wrapOrSkip(description, inCode) + + return "[Java] " + description + } + + fun formatJavaOrLightMethod(method: PsiMethod): String { + val originalDeclaration = method.unwrapped + if (originalDeclaration is KtDeclaration) { + val bindingContext = originalDeclaration.analyze(BodyResolveMode.FULL) + val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, originalDeclaration) + + if (descriptor != null) return formatFunctionDescriptor(descriptor) + } + return formatPsiMethod(method, false, false) + } + + fun formatClass(classOrObject: KtClassOrObject): String { + val bindingContext = classOrObject.analyze(BodyResolveMode.FULL) + val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject) + + if (descriptor is ClassDescriptor) return formatClassDescriptor(descriptor) + return "class " + classOrObject.name!! + } + + fun checkParametersInMethodHierarchy(parameter: PsiParameter): Collection? { + val method = parameter.declarationScope as PsiMethod + + val parametersToDelete = collectParametersHierarchy(method, parameter) + if (parametersToDelete.size > 1) { + if (ApplicationManager.getApplication().isUnitTestMode) { + return parametersToDelete + } + + val message = KotlinBundle.message("delete.param.in.method.hierarchy", formatJavaOrLightMethod(method)) + val exitCode = Messages.showOkCancelDialog( + parameter.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon()) + if (exitCode == Messages.OK) { + return parametersToDelete + } + else { + return null } } - return parametersToDelete; + return parametersToDelete } // TODO: generalize breadth-first search - @NotNull - private static Set collectParametersHierarchy(@NotNull PsiMethod method, @NotNull PsiParameter parameter) { - Deque queue = new ArrayDeque(); - Set visited = new HashSet(); - Set parametersToDelete = new HashSet(); + private fun collectParametersHierarchy(method: PsiMethod, parameter: PsiParameter): Set { + val queue = ArrayDeque() + val visited = HashSet() + val parametersToDelete = HashSet() - queue.add(method); + queue.add(method) while (!queue.isEmpty()) { - PsiMethod currentMethod = queue.poll(); + val currentMethod = queue.poll() - visited.add(currentMethod); - addParameter(currentMethod, parametersToDelete, parameter); + visited.add(currentMethod) + addParameter(currentMethod, parametersToDelete, parameter) - for (PsiMethod superMethod : currentMethod.findSuperMethods(true)) { + for (superMethod in currentMethod.findSuperMethods(true)) { if (!visited.contains(superMethod)) { - queue.offer(superMethod); + queue.offer(superMethod) } } - for (PsiMethod overrider : OverridingMethodsSearch.search(currentMethod)) { + for (overrider in OverridingMethodsSearch.search(currentMethod)) { if (!visited.contains(overrider)) { - queue.offer(overrider); + queue.offer(overrider) } } } - return parametersToDelete; + return parametersToDelete } - private static void addParameter(@NotNull PsiMethod method, @NotNull Set result, @NotNull PsiParameter parameter) { - int parameterIndex = KtPsiUtilKt.parameterIndex(LightClassUtilsKt.getUnwrapped(parameter)); + private fun addParameter(method: PsiMethod, result: MutableSet, parameter: PsiParameter) { + val parameterIndex = parameter.unwrapped!!.parameterIndex() - if (method instanceof KtLightMethod) { - KtDeclaration declaration = ((KtLightMethod) method).getKotlinOrigin(); - if (declaration instanceof KtFunction) { - result.add(((KtFunction) declaration).getValueParameters().get(parameterIndex)); + if (method is KtLightMethod) { + val declaration = method.kotlinOrigin + if (declaration is KtFunction) { + result.add(declaration.valueParameters[parameterIndex]) } } else { - result.add(method.getParameterList().getParameters()[parameterIndex]); + result.add(method.parameterList.parameters[parameterIndex]) } } - public interface SelectElementCallback { - void run(@Nullable PsiElement element); + @Throws(IntroduceRefactoringException::class) + fun selectElement( + editor: Editor, + file: KtFile, + elementKinds: Collection, + callback: (PsiElement?) -> Unit) { + selectElement(editor, file, true, elementKinds, callback) } - public static void selectElement( - @NotNull Editor editor, - @NotNull KtFile file, - @NotNull Collection elementKinds, - @NotNull SelectElementCallback callback - ) throws IntroduceRefactoringException { - selectElement(editor, file, true, elementKinds, callback); - } + @Throws(IntroduceRefactoringException::class) + fun selectElement(editor: Editor, + file: KtFile, + failOnEmptySuggestion: Boolean, + elementKinds: Collection, + callback: (PsiElement?) -> Unit) { + if (editor.selectionModel.hasSelection()) { + var selectionStart = editor.selectionModel.selectionStart + var selectionEnd = editor.selectionModel.selectionEnd - public static void selectElement(@NotNull Editor editor, - @NotNull KtFile file, - boolean failOnEmptySuggestion, - @NotNull Collection elementKinds, - @NotNull SelectElementCallback callback - ) throws IntroduceRefactoringException { - if (editor.getSelectionModel().hasSelection()) { - int selectionStart = editor.getSelectionModel().getSelectionStart(); - int selectionEnd = editor.getSelectionModel().getSelectionEnd(); + var firstElement: PsiElement = file.findElementAt(selectionStart)!! + var lastElement: PsiElement = file.findElementAt(selectionEnd - 1)!! - PsiElement firstElement = file.findElementAt(selectionStart); - PsiElement lastElement = file.findElementAt(selectionEnd - 1); - - if (PsiTreeUtil.getParentOfType(firstElement, KtLiteralStringTemplateEntry.class, KtEscapeStringTemplateEntry.class) == null - && PsiTreeUtil.getParentOfType(lastElement, KtLiteralStringTemplateEntry.class, KtEscapeStringTemplateEntry.class) == null) { - firstElement = PsiUtilsKt.getNextSiblingIgnoringWhitespaceAndComments(firstElement, true); - lastElement = PsiUtilsKt.getPrevSiblingIgnoringWhitespaceAndComments(lastElement, true); - selectionStart = firstElement.getTextRange().getStartOffset(); - selectionEnd = lastElement.getTextRange().getEndOffset(); + if (PsiTreeUtil.getParentOfType(firstElement, KtLiteralStringTemplateEntry::class.java, KtEscapeStringTemplateEntry::class.java) == null && PsiTreeUtil.getParentOfType(lastElement, KtLiteralStringTemplateEntry::class.java, KtEscapeStringTemplateEntry::class.java) == null) { + firstElement = firstElement.getNextSiblingIgnoringWhitespaceAndComments(true)!! + lastElement = lastElement.getPrevSiblingIgnoringWhitespaceAndComments(true)!! + selectionStart = firstElement.textRange.startOffset + selectionEnd = lastElement.textRange.endOffset } - for (CodeInsightUtils.ElementKind elementKind : elementKinds) { - PsiElement element = findElement(file, selectionStart, selectionEnd, failOnEmptySuggestion, elementKind); + for (elementKind in elementKinds) { + val element = findElement(file, selectionStart, selectionEnd, failOnEmptySuggestion, elementKind) if (element != null) { - callback.run(element); - return; + callback(element) + return } } - callback.run(null); + callback(null) } else { - int offset = editor.getCaretModel().getOffset(); - smartSelectElement(editor, file, offset, failOnEmptySuggestion, elementKinds, callback); + val offset = editor.caretModel.offset + smartSelectElement(editor, file, offset, failOnEmptySuggestion, elementKinds, callback) } } - public static List getSmartSelectSuggestions( - @NotNull PsiFile file, - int offset, - @NotNull CodeInsightUtils.ElementKind elementKind - ) throws IntroduceRefactoringException { + @Throws(IntroduceRefactoringException::class) + fun getSmartSelectSuggestions( + file: PsiFile, + offset: Int, + elementKind: CodeInsightUtils.ElementKind): List { if (offset < 0) { - return new ArrayList(); + return ArrayList() } - PsiElement element = file.findElementAt(offset); - if (element == null) { - return new ArrayList(); - } - if (element instanceof PsiWhiteSpace) { - return getSmartSelectSuggestions(file, offset - 1, elementKind); + var element: PsiElement? = file.findElementAt(offset) ?: return ArrayList() + if (element is PsiWhiteSpace) { + return getSmartSelectSuggestions(file, offset - 1, elementKind) } - List elements = new ArrayList(); - while (element != null && !(element instanceof KtBlockExpression && !(element.getParent() instanceof KtFunctionLiteral)) && - !(element instanceof KtNamedFunction) - && !(element instanceof KtClassBody)) { - boolean addElement = false; - boolean keepPrevious = true; + val elements = ArrayList() + while (element != null && !(element is KtBlockExpression && element.parent !is KtFunctionLiteral) && + element !is KtNamedFunction + && element !is KtClassBody) { + var addElement = false + var keepPrevious = true - if (element instanceof KtTypeElement) { - addElement = elementKind == CodeInsightUtils.ElementKind.TYPE_ELEMENT; + if (element is KtTypeElement) { + addElement = elementKind == CodeInsightUtils.ElementKind.TYPE_ELEMENT if (!addElement) { - keepPrevious = false; + keepPrevious = false } } - else if (element instanceof KtExpression && !(element instanceof KtStatementExpression)) { - addElement = elementKind == CodeInsightUtils.ElementKind.EXPRESSION; + else if (element is KtExpression && element !is KtStatementExpression) { + addElement = elementKind == CodeInsightUtils.ElementKind.EXPRESSION if (addElement) { - if (element instanceof KtParenthesizedExpression) { - addElement = false; + if (element is KtParenthesizedExpression) { + addElement = false } else if (KtPsiUtil.isLabelIdentifierExpression(element)) { - addElement = false; + addElement = false } - else if (element.getParent() instanceof KtQualifiedExpression) { - KtQualifiedExpression qualifiedExpression = (KtQualifiedExpression) element.getParent(); - if (qualifiedExpression.getReceiverExpression() != element) { - addElement = false; + else if (element.parent is KtQualifiedExpression) { + val qualifiedExpression = element.parent as KtQualifiedExpression + if (qualifiedExpression.receiverExpression !== element) { + addElement = false } } - else if (element.getParent() instanceof KtCallElement - || element.getParent() instanceof KtThisExpression - || PsiTreeUtil.getParentOfType(element, KtSuperExpression.class) != null) { - addElement = false; + else if (element.parent is KtCallElement + || element.parent is KtThisExpression + || PsiTreeUtil.getParentOfType(element, KtSuperExpression::class.java) != null) { + addElement = false } - else if (element.getParent() instanceof KtOperationExpression) { - KtOperationExpression operationExpression = (KtOperationExpression) element.getParent(); - if (operationExpression.getOperationReference() == element) { - addElement = false; + else if (element.parent is KtOperationExpression) { + val operationExpression = element.parent as KtOperationExpression + if (operationExpression.operationReference === element) { + addElement = false } } if (addElement) { - KtExpression expression = (KtExpression)element; - BindingContext bindingContext = ResolutionUtils.analyze(expression, BodyResolveMode.FULL); - KotlinType expressionType = bindingContext.getType(expression); + val bindingContext = element.analyze(BodyResolveMode.FULL) + val expressionType = bindingContext.getType(element) if (expressionType == null || KotlinBuiltIns.isUnit(expressionType)) { - addElement = false; + addElement = false } } } } if (addElement) { - elements.add((KtElement) element); + elements.add(element as KtElement) } if (!keepPrevious) { - elements.clear(); + elements.clear() } - element = element.getParent(); + element = element.parent } - return elements; + return elements } - private static void smartSelectElement( - @NotNull Editor editor, - @NotNull final PsiFile file, - final int offset, - boolean failOnEmptySuggestion, - @NotNull Collection elementKinds, - @NotNull final SelectElementCallback callback - ) throws IntroduceRefactoringException { - List elements = CollectionsKt.flatMap( - elementKinds, - new Function1>() { - @Override - public Iterable invoke(CodeInsightUtils.ElementKind kind) { - return getSmartSelectSuggestions(file, offset, kind); - } + @Throws(IntroduceRefactoringException::class) + private fun smartSelectElement( + editor: Editor, + file: PsiFile, + offset: Int, + failOnEmptySuggestion: Boolean, + elementKinds: Collection, + callback: (PsiElement?) -> Unit) { + val elements = elementKinds.flatMap { kind -> getSmartSelectSuggestions(file, offset, kind) } + if (elements.size == 0) { + if (failOnEmptySuggestion) + throw IntroduceRefactoringException( + KotlinRefactoringBundle.message("cannot.refactor.not.expression")) + callback(null) + return + } + + if (elements.size == 1 || ApplicationManager.getApplication().isUnitTestMode) { + callback(elements[0]) + return + } + + val model = DefaultListModel() + for (element in elements) { + model.addElement(element) + } + + val highlighter = ScopeHighlighter(editor) + + val list = JBList(model) + + list.setCellRenderer(object : DefaultListCellRenderer() { + override fun getListCellRendererComponent(list: JList<*>, value: Any?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component { + val rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus) + val element = value as KtElement? + if (element!!.isValid) { + text = getExpressionShortText(element) } - ); - if (elements.size() == 0) { - if (failOnEmptySuggestion) throw new IntroduceRefactoringException( - KotlinRefactoringBundle.message("cannot.refactor.not.expression")); - callback.run(null); - return; - } - - if (elements.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { - callback.run(elements.get(0)); - return; - } - - final DefaultListModel model = new DefaultListModel(); - for (PsiElement element : elements) { - model.addElement(element); - } - - final ScopeHighlighter highlighter = new ScopeHighlighter(editor); - - final JList list = new JBList(model); - - list.setCellRenderer(new DefaultListCellRenderer() { - @Override - public Component getListCellRendererComponent(@NotNull JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - Component rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - KtElement element = (KtElement) value; - if (element.isValid()) { - setText(getExpressionShortText(element)); - } - return rendererComponent; + return rendererComponent } - }); + }) - list.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(@NotNull ListSelectionEvent e) { - highlighter.dropHighlight(); - int selectedIndex = list.getSelectedIndex(); - if (selectedIndex < 0) return; - KtElement expression = (KtElement) model.get(selectedIndex); - List toExtract = new ArrayList(); - toExtract.add(expression); - highlighter.highlight(expression, toExtract); - } - }); + list.addListSelectionListener(ListSelectionListener { + highlighter.dropHighlight() + val selectedIndex = list.getSelectedIndex() + if (selectedIndex < 0) return@ListSelectionListener + val toExtract = ArrayList() + toExtract.add(model.get(selectedIndex)) + highlighter.highlight(model.get(selectedIndex), toExtract) + }) - String title = "Elements"; - if (elementKinds.size() == 1) { - switch (elementKinds.iterator().next()) { - case EXPRESSION: - title = "Expressions"; - break; - case TYPE_ELEMENT: - case TYPE_CONSTRUCTOR: - title = "Types"; - break; + var title = "Elements" + if (elementKinds.size == 1) { + when (elementKinds.iterator().next()) { + CodeInsightUtils.ElementKind.EXPRESSION -> title = "Expressions" + CodeInsightUtils.ElementKind.TYPE_ELEMENT, CodeInsightUtils.ElementKind.TYPE_CONSTRUCTOR -> title = "Types" } } - JBPopupFactory.getInstance().createListPopupBuilder(list). - setTitle(title).setMovable(false).setResizable(false). - setRequestFocus(true).setItemChoosenCallback(new Runnable() { - @Override - public void run() { - callback.run((KtElement) list.getSelectedValue()); + JBPopupFactory.getInstance().createListPopupBuilder(list).setTitle(title).setMovable(false).setResizable(false).setRequestFocus(true).setItemChoosenCallback { callback(list.getSelectedValue() as KtElement) }.addListener(object : JBPopupAdapter() { + override fun onClosed(event: LightweightWindowEvent?) { + highlighter.dropHighlight() } - }).addListener(new JBPopupAdapter() { - @Override - public void onClosed(LightweightWindowEvent event) { - highlighter.dropHighlight(); - } - }).createPopup().showInBestPositionFor(editor); + }).createPopup().showInBestPositionFor(editor) } - public static String getExpressionShortText(@NotNull KtElement element) { - String text = ElementRenderingUtilsKt.renderTrimmed(element); - int firstNewLinePos = text.indexOf('\n'); - String trimmedText = text.substring(0, firstNewLinePos != -1 ? firstNewLinePos : Math.min(100, text.length())); - if (trimmedText.length() != text.length()) trimmedText += " ..."; - return trimmedText; + fun getExpressionShortText(element: KtElement): String { + val text = element.renderTrimmed() + val firstNewLinePos = text.indexOf('\n') + var trimmedText = text.substring(0, if (firstNewLinePos != -1) firstNewLinePos else Math.min(100, text.length)) + if (trimmedText.length != text.length) trimmedText += " ..." + return trimmedText } - @Nullable - private static PsiElement findElement( - @NotNull KtFile file, - int startOffset, - int endOffset, - boolean failOnNoExpression, - @NotNull CodeInsightUtils.ElementKind elementKind - ) throws IntroduceRefactoringException { - PsiElement element = CodeInsightUtils.findElement(file, startOffset, endOffset, elementKind); + @Throws(IntroduceRefactoringException::class) + private fun findElement( + file: KtFile, + startOffset: Int, + endOffset: Int, + failOnNoExpression: Boolean, + elementKind: CodeInsightUtils.ElementKind): PsiElement? { + var element = CodeInsightUtils.findElement(file, startOffset, endOffset, elementKind) if (element == null && elementKind == CodeInsightUtils.ElementKind.EXPRESSION) { - element = IntroduceUtilKt.findExpressionOrStringFragment(file, startOffset, endOffset); + element = findExpressionOrStringFragment(file, startOffset, endOffset) } if (element == null) { //todo: if it's infix expression => add (), then commit document then return new created expression if (failOnNoExpression) { - throw new IntroduceRefactoringException(KotlinRefactoringBundle.message("cannot.refactor.not.expression")); + throw IntroduceRefactoringException(KotlinRefactoringBundle.message("cannot.refactor.not.expression")) } - return null; + return null } - return element; + return element } - public static class IntroduceRefactoringException extends RuntimeException { - private final String myMessage; - - public IntroduceRefactoringException(String message) { - myMessage = message; - } - - @Override - public String getMessage() { - return myMessage; - } + class IntroduceRefactoringException(private val myMessage: String) : RuntimeException() { + override val message: String? + get() = myMessage } - } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/safeDelete/KotlinOverridingDialog.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/safeDelete/KotlinOverridingDialog.java index 96853cfc590..1bde7e5e02c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/safeDelete/KotlinOverridingDialog.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/safeDelete/KotlinOverridingDialog.java @@ -110,7 +110,7 @@ class KotlinOverridingDialog extends DialogWrapper { assert element instanceof PsiMethod : "Method accepts only kotlin functions/properties and java methods, but '" + element.getText() + "' was found"; - return KotlinRefactoringUtil2.formatPsiMethod((PsiMethod) element, true, false); + return KotlinRefactoringUtil2.INSTANCE.formatPsiMethod((PsiMethod) element, true, false); } @Override diff --git a/idea/tests/org/jetbrains/kotlin/idea/AbstractExpressionSelectionTest.java b/idea/tests/org/jetbrains/kotlin/idea/AbstractExpressionSelectionTest.java index c5fab00cbc0..1920345a5f5 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/AbstractExpressionSelectionTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/AbstractExpressionSelectionTest.java @@ -18,8 +18,9 @@ package org.jetbrains.kotlin.idea; import com.intellij.psi.PsiElement; import com.intellij.testFramework.LightCodeInsightTestCase; +import kotlin.Unit; +import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils; import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2; import org.jetbrains.kotlin.psi.KtFile; @@ -34,15 +35,16 @@ public abstract class AbstractExpressionSelectionTest extends LightCodeInsightTe final String expectedExpression = KotlinTestUtils.getLastCommentInFile((KtFile) getFile()); try { - KotlinRefactoringUtil2.selectElement( + KotlinRefactoringUtil2.INSTANCE.selectElement( getEditor(), (KtFile) getFile(), Collections.singletonList(CodeInsightUtils.ElementKind.EXPRESSION), - new KotlinRefactoringUtil2.SelectElementCallback() { + new Function1() { @Override - public void run(@Nullable PsiElement element) { + public Unit invoke(PsiElement element) { assertNotNull("Selected expression mustn't be null", element); assertEquals(expectedExpression, element.getText()); + return Unit.INSTANCE; } } ); diff --git a/idea/tests/org/jetbrains/kotlin/idea/AbstractSmartSelectionTest.java b/idea/tests/org/jetbrains/kotlin/idea/AbstractSmartSelectionTest.java index 39f52eac916..8d000820333 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/AbstractSmartSelectionTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/AbstractSmartSelectionTest.java @@ -34,12 +34,12 @@ public abstract class AbstractSmartSelectionTest extends LightCodeInsightTestCas configureByFile(path); String expectedResultText = KotlinTestUtils.getLastCommentInFile((KtFile) getFile()); - List elements = KotlinRefactoringUtil2.getSmartSelectSuggestions( + List elements = KotlinRefactoringUtil2.INSTANCE.getSmartSelectSuggestions( getFile(), getEditor().getCaretModel().getOffset(), CodeInsightUtils.ElementKind.EXPRESSION); List textualExpressions = new ArrayList(); for (KtElement element : elements) { - textualExpressions.add(KotlinRefactoringUtil2.getExpressionShortText(element)); + textualExpressions.add(KotlinRefactoringUtil2.INSTANCE.getExpressionShortText(element)); } assertEquals(expectedResultText, StringUtil.join(textualExpressions, "\n")); } diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/nameSuggester/KotlinNameSuggesterTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/nameSuggester/KotlinNameSuggesterTest.kt index 0bea7a50b22..0aeedbd02fa 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/nameSuggester/KotlinNameSuggesterTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/nameSuggester/KotlinNameSuggesterTest.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.idea.refactoring.nameSuggester import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.PsiElement import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils @@ -30,6 +29,7 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.KotlinTestUtils +import java.lang.AssertionError class KotlinNameSuggesterTest : LightCodeInsightFixtureTestCase() { fun testArrayList() { doTest() } @@ -90,19 +90,17 @@ class KotlinNameSuggesterTest : LightCodeInsightFixtureTestCase() { if (withRuntime) { ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) } - KotlinRefactoringUtil2.selectElement(myFixture.editor, file, listOf(CodeInsightUtils.ElementKind.EXPRESSION), object : KotlinRefactoringUtil2.SelectElementCallback { - override fun run(element: PsiElement?) { - val names = KotlinNameSuggester - .suggestNamesByExpressionAndType(element as KtExpression, - null, - element.analyze(BodyResolveMode.PARTIAL), - { true }, - "value") - .sorted() - val result = StringUtil.join(names, "\n").trim() - assertEquals(expectedResultText, result) - } - }) + KotlinRefactoringUtil2.selectElement(myFixture.editor, file, listOf(CodeInsightUtils.ElementKind.EXPRESSION)) { + val names = KotlinNameSuggester + .suggestNamesByExpressionAndType(it as KtExpression, + null, + it.analyze(BodyResolveMode.PARTIAL), + { true }, + "value") + .sorted() + val result = StringUtil.join(names, "\n").trim() + assertEquals(expectedResultText, result) + } } catch (e: KotlinRefactoringUtil2.IntroduceRefactoringException) { throw AssertionError("Failed to find expression: " + e.message)