diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt index e17c4a217bb..7ac2b72f897 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt @@ -32,11 +32,12 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileVisitor import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager -import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter +import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.j2k.* +import org.jetbrains.kotlin.j2k.ConverterSettings +import org.jetbrains.kotlin.j2k.JavaToKotlinConverter import java.io.File import java.io.IOException import java.util.ArrayList @@ -50,7 +51,7 @@ public class JavaToKotlinAction : AnAction() { var converterResult: JavaToKotlinConverter.FilesResult? = null fun convert() { - val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaReferenceSearcher, IdeaResolverForConverter, IdeaDocCommentConverter) + val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices) converterResult = converter.filesToKotlin(javaFiles, J2kPostProcessor(formatCode = true), ProgressManager.getInstance().getProgressIndicator()) } diff --git a/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPastePostProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPastePostProcessor.kt index ba1bb664a47..256300951ad 100644 --- a/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPastePostProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPastePostProcessor.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference import org.jetbrains.kotlin.idea.codeInsight.KotlinCopyPasteReferenceProcessor import org.jetbrains.kotlin.idea.codeInsight.KotlinReferenceData import org.jetbrains.kotlin.idea.editor.JetEditorOptions +import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor import org.jetbrains.kotlin.idea.util.ImportInsertHelper @@ -159,9 +160,7 @@ public class ConvertJavaCopyPastePostProcessor : CopyPastePostProcessor() diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaDocCommentConverter.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaDocCommentConverter.kt new file mode 100644 index 00000000000..557a4b9844d --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaDocCommentConverter.kt @@ -0,0 +1,217 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.j2k + +import com.intellij.ide.highlighter.HtmlFileType +import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFileFactory +import com.intellij.psi.PsiWhiteSpace +import com.intellij.psi.XmlRecursiveElementVisitor +import com.intellij.psi.javadoc.PsiDocComment +import com.intellij.psi.javadoc.PsiDocTag +import com.intellij.psi.javadoc.PsiDocToken +import com.intellij.psi.javadoc.PsiInlineDocTag +import com.intellij.psi.xml.XmlFile +import com.intellij.psi.xml.XmlTag +import com.intellij.psi.xml.XmlText +import com.intellij.psi.xml.XmlTokenType +import org.jetbrains.kotlin.j2k.DocCommentConverter +import org.jetbrains.kotlin.j2k.content + +object IdeaDocCommentConverter : DocCommentConverter { + override fun convertDocComment(docComment: PsiDocComment): String { + val html = StringBuilder { + appendJavadocElements(docComment.getDescriptionElements()) + + tagsLoop@ + for (tag in docComment.getTags()) { + when (tag.getName()) { + "deprecated" -> continue@tagsLoop + "see" -> append("@see ${convertJavadocLink(tag.content())}\n") + else -> appendJavadocElements(tag.getChildren()).append("\n") + } + } + }.toString() + + if (html.trim().isEmpty() && docComment.findTagByName("deprecated") != null) { + // @deprecated was the only content of the doc comment; we can drop the comment + return "" + } + + val htmlFile = PsiFileFactory.getInstance(docComment.getProject()).createFileFromText( + "javadoc.html", HtmlFileType.INSTANCE, html) + val htmlToMarkdownConverter = HtmlToMarkdownConverter() + htmlFile.accept(htmlToMarkdownConverter) + return htmlToMarkdownConverter.result + } + + private fun StringBuilder.appendJavadocElements(elements: Array): StringBuilder { + elements.forEach { + if (it is PsiInlineDocTag) { + append(convertInlineDocTag(it)) + } + else { + append(it.getText()) + } + } + return this + } + + private fun convertInlineDocTag(tag: PsiInlineDocTag) = when(tag.getName()) { + "code", "literal" -> { + val text = tag.getDataElements().map { it.getText() }.join("") + val escaped = StringUtil.escapeXml(text.trimStart()) + if (tag.getName() == "code") "$escaped" else escaped + } + + "link", "linkplain" -> { + val valueElement = tag.linkElement() + val labelText = tag.getDataElements().firstOrNull { it is PsiDocToken }?.getText() ?: "" + val kdocLink = convertJavadocLink(valueElement?.getText()) + val linkText = if (labelText.isEmpty()) kdocLink else StringUtil.escapeXml(labelText) + "$linkText" + } + + else -> tag.getText() + } + + private fun convertJavadocLink(link: String?): String = + if (link != null) link.substringBefore('(').replace('#', '.') else "" + + private fun PsiDocTag.linkElement(): PsiElement? = + getValueElement() ?: getDataElements().firstOrNull { it !is PsiWhiteSpace } + + private class HtmlToMarkdownConverter() : XmlRecursiveElementVisitor() { + private enum class ListType { Ordered, Unordered; } + data class MarkdownSpan(val prefix: String, val suffix: String) { + companion object { + val Empty = MarkdownSpan("", "") + + fun wrap(text: String) = MarkdownSpan(text, text) + fun prefix(text: String) = MarkdownSpan(text, "") + } + } + + + val result: String + get() = markdownBuilder.toString() + + private val markdownBuilder = StringBuilder("/**") + private var afterLineBreak = false + private var whitespaceIsPartOfText = true + private var currentListType = ListType.Unordered + + override fun visitWhiteSpace(space: PsiWhiteSpace) { + super.visitWhiteSpace(space) + + if (whitespaceIsPartOfText) { + appendPendingText() + markdownBuilder.append(space.getText()) + if (space.textContains('\n')) { + afterLineBreak = true + } + } + } + + override fun visitElement(element: PsiElement) { + super.visitElement(element) + + val tokenType = element.getNode().getElementType() + if (tokenType == XmlTokenType.XML_DATA_CHARACTERS || tokenType == XmlTokenType.XML_CHAR_ENTITY_REF) { + appendPendingText() + markdownBuilder.append(element.getText()) + } + } + + override fun visitXmlTag(tag: XmlTag) { + withWhitespaceAsPartOfText(false) { + val oldListType = currentListType + val atLineStart = afterLineBreak + appendPendingText() + val (openingMarkdown, closingMarkdown) = getMarkdownForTag(tag, atLineStart) + markdownBuilder.append(openingMarkdown) + + super.visitXmlTag(tag) + + markdownBuilder.append(closingMarkdown) + currentListType = oldListType + } + } + + override fun visitXmlText(text: XmlText) { + withWhitespaceAsPartOfText(true) { + super.visitXmlText(text) + } + } + + private inline fun withWhitespaceAsPartOfText(newValue: Boolean, block: () -> Unit) { + val oldValue = whitespaceIsPartOfText + whitespaceIsPartOfText = newValue + try { + block() + } + finally { + whitespaceIsPartOfText = oldValue + } + } + + private fun getMarkdownForTag(tag: XmlTag, atLineStart: Boolean): MarkdownSpan = when(tag.getName()) { + "b", "strong" -> MarkdownSpan.wrap("**") + + "p" -> if (atLineStart) MarkdownSpan.prefix("\n * ") else MarkdownSpan.prefix("\n *\n *") + + "i", "em" -> MarkdownSpan.wrap("*") + + "s", "del" -> MarkdownSpan.wrap("~~") + + "code" -> MarkdownSpan.wrap("`") + + "a" -> { + if (tag.getAttributeValue("docref") != null) { + val docRef = tag.getAttributeValue("docref") + val innerText = tag.getValue().getText() + if (docRef == innerText) MarkdownSpan("[", "]") else MarkdownSpan("[", "][$docRef]") + } + else { + MarkdownSpan("[", "](${tag.getAttributeValue("href")})") + } + } + + "ul" -> { currentListType = ListType.Unordered; MarkdownSpan.Empty } + + "ol" -> { currentListType = ListType.Ordered; MarkdownSpan.Empty } + + "li" -> if (currentListType == ListType.Unordered) MarkdownSpan.prefix(" * ") else MarkdownSpan.prefix(" 1. ") + + else -> MarkdownSpan.Empty + } + + private fun appendPendingText() { + if (afterLineBreak ) { + markdownBuilder.append(" * ") + afterLineBreak = false + } + } + + override fun visitXmlFile(file: XmlFile) { + super.visitXmlFile(file) + + markdownBuilder.append(" */") + } + } +} diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaJavaToKotlinServices.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaJavaToKotlinServices.kt new file mode 100644 index 00000000000..7023490061d --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaJavaToKotlinServices.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.j2k + +import org.jetbrains.kotlin.j2k.* + +object IdeaJavaToKotlinServices: JavaToKotlinConverterServices { + override val referenceSearcher: ReferenceSearcher + get() = IdeaReferenceSearcher + override val resolverForConverter: ResolverForConverter + get() = IdeaResolverForConverter + override val docCommentConverter: DocCommentConverter + get() = IdeaDocCommentConverter +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaReferenceSearcher.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaReferenceSearcher.kt new file mode 100644 index 00000000000..c5948cf3e65 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/IdeaReferenceSearcher.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.j2k + +import com.intellij.lang.java.JavaLanguage +import com.intellij.openapi.fileTypes.FileType +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiReference +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.LocalSearchScope +import com.intellij.psi.search.searches.ClassInheritorsSearch +import com.intellij.psi.search.searches.OverridingMethodsSearch +import com.intellij.psi.search.searches.ReferencesSearch +import org.jetbrains.kotlin.idea.JetLanguage +import org.jetbrains.kotlin.j2k.ReferenceSearcher +import java.util.* + +public object IdeaReferenceSearcher: ReferenceSearcher { + override fun findLocalUsages(element: PsiElement, scope: PsiElement) = ReferencesSearch.search(element, LocalSearchScope(scope)).findAll() + + override fun hasInheritors(`class`: PsiClass) = ClassInheritorsSearch.search(`class`, false).any() + + override fun hasOverrides(method: PsiMethod) = OverridingMethodsSearch.search(method, false).any() + + override fun findUsagesForExternalCodeProcessing(element: PsiElement, searchJava: Boolean, searchKotlin: Boolean): Collection { + val fileTypes = ArrayList() + if (searchJava) { + fileTypes.add(JavaLanguage.INSTANCE.getAssociatedFileType()!!) + } + if (searchKotlin) { + fileTypes.add(JetLanguage.INSTANCE.getAssociatedFileType()!!) + } + val searchScope = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.projectScope(element.getProject()), *fileTypes.toTypedArray()) + return ReferencesSearch.search(element, searchScope).findAll() + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterMethodUsageProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterMethodUsageProcessor.kt index 206873cb47f..93cc6296caa 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterMethodUsageProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterMethodUsageProcessor.kt @@ -16,8 +16,6 @@ package org.jetbrains.kotlin.idea.refactoring.introduce.introduceParameter -import com.intellij.lang.java.JavaLanguage -import com.intellij.openapi.util.Ref import com.intellij.psi.PsiElement import com.intellij.psi.PsiExpression import com.intellij.psi.PsiMethod @@ -25,10 +23,7 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.refactoring.introduceParameter.IntroduceParameterData import com.intellij.refactoring.introduceParameter.IntroduceParameterMethodUsagesProcessor import com.intellij.usageView.UsageInfo -import com.intellij.util.ArrayUtil import com.intellij.util.containers.MultiMap -import gnu.trove.TIntArrayList -import org.jetbrains.kotlin.asJava.KotlinLightMethod import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -36,24 +31,20 @@ import org.jetbrains.kotlin.idea.JetFileType import org.jetbrains.kotlin.idea.caches.resolve.getJavaMethodDescriptor import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.core.refactoring.j2k -import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter -import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureData import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo import org.jetbrains.kotlin.idea.refactoring.changeSignature.originalBaseFunctionDescriptor -import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.* +import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetCallableDefinitionUsage +import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetConstructorDelegationCallUsage +import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionCallUsage +import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetUsageInfo import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest +import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.j2k.ConverterSettings -import org.jetbrains.kotlin.j2k.IdeaReferenceSearcher -import org.jetbrains.kotlin.j2k.JavaToKotlinConverter import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch -import org.jetbrains.kotlin.types.JetType -import java.util.Arrays import java.util.Collections -import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders public class KotlinIntroduceParameterMethodUsageProcessor : IntroduceParameterMethodUsagesProcessor { override fun isMethodUsage(usage: UsageInfo): Boolean = (usage.getElement() as? JetElement)?.let { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt index d67018b192c..d4332d58ade 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt @@ -63,12 +63,10 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getJavaMemberDescriptor import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.core.getPackage -import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter +import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.string.collapseSpaces import org.jetbrains.kotlin.j2k.ConverterSettings -import org.jetbrains.kotlin.j2k.IdeaDocCommentConverter -import org.jetbrains.kotlin.j2k.IdeaReferenceSearcher import org.jetbrains.kotlin.j2k.JavaToKotlinConverter import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode @@ -77,10 +75,10 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.AnalyzingUtils import org.jetbrains.kotlin.resolve.BindingContext import java.io.File +import java.lang.annotation.Retention import java.util.ArrayList import java.util.Collections import javax.swing.Icon -import java.lang.annotation.Retention fun PsiElement.getAndRemoveCopyableUserData(key: Key): T? { val data = getCopyableUserData(key) @@ -572,9 +570,7 @@ fun PsiExpression.j2k(): JetExpression? { val project = getProject() val j2kConverter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, - IdeaReferenceSearcher, - IdeaResolverForConverter, - IdeaDocCommentConverter) + IdeaJavaToKotlinServices) val text = j2kConverter.elementsToKotlin(listOf(this)).results.single()?.text ?: return null //TODO: insert imports return JetPsiFactory(getProject()).createExpression(text) } diff --git a/j2k/j2k.iml b/j2k/j2k.iml index 3f387a96335..abdb40a0587 100644 --- a/j2k/j2k.iml +++ b/j2k/j2k.iml @@ -8,12 +8,14 @@ - + + + \ No newline at end of file diff --git a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt index 2f256555293..ab6cb624773 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt @@ -39,9 +39,7 @@ class Converter private constructor( private val elementToConvert: PsiElement, val settings: ConverterSettings, val inConversionScope: (PsiElement) -> Boolean, - val referenceSearcher: ReferenceSearcher, - val resolverForConverter: ResolverForConverter, - private val docCommentConverter: DocCommentConverter, + val services: JavaToKotlinConverterServices, private val commonState: Converter.CommonState, private val personalState: Converter.PersonalState ) { @@ -61,20 +59,20 @@ class Converter private constructor( public val specialContext: PsiElement? = personalState.specialContext + public val referenceSearcher: CachingReferenceSearcher = CachingReferenceSearcher(services.referenceSearcher) + companion object { public fun create(elementToConvert: PsiElement, settings: ConverterSettings, inConversionScope: (PsiElement) -> Boolean, - referenceSearcher: ReferenceSearcher, resolverForConverter: ResolverForConverter, - docCommentConverter: DocCommentConverter, usageProcessingsCollector: (UsageProcessing) -> Unit): Converter { + services: JavaToKotlinConverterServices, usageProcessingsCollector: (UsageProcessing) -> Unit): Converter { return Converter(elementToConvert, settings, inConversionScope, - CachingReferenceSearcher(referenceSearcher), - resolverForConverter, docCommentConverter, CommonState(usageProcessingsCollector), PersonalState(null)) + services, CommonState(usageProcessingsCollector), PersonalState(null)) } } public fun withSpecialContext(context: PsiElement): Converter = withState(PersonalState(context)) private fun withState(state: PersonalState): Converter - = Converter(elementToConvert, settings, inConversionScope, referenceSearcher, resolverForConverter, docCommentConverter, commonState, state) + = Converter(elementToConvert, settings, inConversionScope, services, commonState, state) private fun createDefaultCodeConverter() = CodeConverter(this, DefaultExpressionConverter(), DefaultStatementConverter(), null) @@ -98,7 +96,7 @@ class Converter private constructor( { usageProcessings -> unfoldDeferredElements(usageProcessings) - val builder = CodeBuilder(elementToConvert, docCommentConverter) + val builder = CodeBuilder(elementToConvert, services.docCommentConverter) builder.append(element) Result(builder.resultText, builder.importsToAdd) }, @@ -322,14 +320,14 @@ class Converter private constructor( addUsageProcessing(FieldToPropertyProcessing(field, correction?.name ?: field.getName()!!, propertyType.isNullable)) return Property(name, - annotations, - modifiers, - propertyType, - deferredElement { codeConverter -> codeConverter.convertExpression(field.getInitializer(), field.getType()) }, - isVal, - typeToDeclare != null, - shouldGenerateDefaultInitializer(referenceSearcher, field), - if (correction != null) correction.setterAccess else modifiers.accessModifier() + annotations, + modifiers, + propertyType, + deferredElement { codeConverter -> codeConverter.convertExpression(field.getInitializer(), field.getType()) }, + isVal, + typeToDeclare != null, + shouldGenerateDefaultInitializer(referenceSearcher, field), + if (correction != null) correction.setterAccess else modifiers.accessModifier() ).assignPrototype(field) } } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/DocCommentConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/DocCommentConverter.kt index c32a01d8b04..8988d5d21cb 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/DocCommentConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/DocCommentConverter.kt @@ -16,18 +16,10 @@ package org.jetbrains.kotlin.j2k -import com.intellij.ide.highlighter.HtmlFileType -import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.* +import com.intellij.psi.JavaDocTokenType +import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.javadoc.PsiDocTag -import com.intellij.psi.javadoc.PsiDocToken -import com.intellij.psi.javadoc.PsiInlineDocTag -import com.intellij.psi.xml.XmlFile -import com.intellij.psi.xml.XmlTag -import com.intellij.psi.xml.XmlText -import com.intellij.psi.xml.XmlTokenType -import java.util.Stack interface DocCommentConverter { fun convertDocComment(docComment: PsiDocComment): String @@ -37,193 +29,10 @@ object EmptyDocCommentConverter: DocCommentConverter { override fun convertDocComment(docComment: PsiDocComment) = docComment.text } -object IdeaDocCommentConverter : DocCommentConverter { - override fun convertDocComment(docComment: PsiDocComment): String { - val html = StringBuilder { - appendJavadocElements(docComment.getDescriptionElements()) - - tagsLoop@ - for (tag in docComment.getTags()) { - when (tag.getName()) { - "deprecated" -> continue@tagsLoop - "see" -> append("@see ${convertJavadocLink(tag.content())}\n") - else -> appendJavadocElements(tag.getChildren()).append("\n") - } - } - }.toString() - - if (html.trim().isEmpty() && docComment.findTagByName("deprecated") != null) { - // @deprecated was the only content of the doc comment; we can drop the comment - return "" - } - - val htmlFile = PsiFileFactory.getInstance(docComment.getProject()).createFileFromText( - "javadoc.html", HtmlFileType.INSTANCE, html) - val htmlToMarkdownConverter = HtmlToMarkdownConverter() - htmlFile.accept(htmlToMarkdownConverter) - return htmlToMarkdownConverter.result - } - - private fun StringBuilder.appendJavadocElements(elements: Array): StringBuilder { - elements.forEach { - if (it is PsiInlineDocTag) { - append(convertInlineDocTag(it)) - } - else { - append(it.getText()) - } - } - return this - } - - private fun convertInlineDocTag(tag: PsiInlineDocTag) = when(tag.getName()) { - "code", "literal" -> { - val text = tag.getDataElements().map { it.getText() }.join("") - val escaped = StringUtil.escapeXml(text.trimStart()) - if (tag.getName() == "code") "$escaped" else escaped - } - - "link", "linkplain" -> { - val valueElement = tag.linkElement() - val labelText = tag.getDataElements().firstOrNull { it is PsiDocToken }?.getText() ?: "" - val kdocLink = convertJavadocLink(valueElement?.getText()) - val linkText = if (labelText.isEmpty()) kdocLink else StringUtil.escapeXml(labelText) - "$linkText" - } - - else -> tag.getText() - } - - private fun convertJavadocLink(link: String?): String = - if (link != null) link.substringBefore('(').replace('#', '.') else "" - - private fun PsiDocTag.linkElement(): PsiElement? = - getValueElement() ?: getDataElements().firstOrNull { it !is PsiWhiteSpace } - - private class HtmlToMarkdownConverter() : XmlRecursiveElementVisitor() { - private enum class ListType { Ordered, Unordered; } - data class MarkdownSpan(val prefix: String, val suffix: String) { - companion object { - val Empty = MarkdownSpan("", "") - - fun wrap(text: String) = MarkdownSpan(text, text) - fun prefix(text: String) = MarkdownSpan(text, "") - } - } - - - val result: String - get() = markdownBuilder.toString() - - private val markdownBuilder = StringBuilder("/**") - private var afterLineBreak = false - private var whitespaceIsPartOfText = true - private var currentListType = ListType.Unordered - - override fun visitWhiteSpace(space: PsiWhiteSpace) { - super.visitWhiteSpace(space) - - if (whitespaceIsPartOfText) { - appendPendingText() - markdownBuilder.append(space.getText()) - if (space.textContains('\n')) { - afterLineBreak = true - } - } - } - - override fun visitElement(element: PsiElement) { - super.visitElement(element) - - val tokenType = element.getNode().getElementType() - if (tokenType == XmlTokenType.XML_DATA_CHARACTERS || tokenType == XmlTokenType.XML_CHAR_ENTITY_REF) { - appendPendingText() - markdownBuilder.append(element.getText()) - } - } - - override fun visitXmlTag(tag: XmlTag) { - withWhitespaceAsPartOfText(false) { - val oldListType = currentListType - val atLineStart = afterLineBreak - appendPendingText() - val (openingMarkdown, closingMarkdown) = getMarkdownForTag(tag, atLineStart) - markdownBuilder.append(openingMarkdown) - - super.visitXmlTag(tag) - - markdownBuilder.append(closingMarkdown) - currentListType = oldListType - } - } - - override fun visitXmlText(text: XmlText) { - withWhitespaceAsPartOfText(true) { - super.visitXmlText(text) - } - } - - private inline fun withWhitespaceAsPartOfText(newValue: Boolean, block: () -> Unit) { - val oldValue = whitespaceIsPartOfText - whitespaceIsPartOfText = newValue - try { - block() - } - finally { - whitespaceIsPartOfText = oldValue - } - } - - private fun getMarkdownForTag(tag: XmlTag, atLineStart: Boolean): MarkdownSpan = when(tag.getName()) { - "b", "strong" -> MarkdownSpan.wrap("**") - - "p" -> if (atLineStart) MarkdownSpan.prefix("\n * ") else MarkdownSpan.prefix("\n *\n *") - - "i", "em" -> MarkdownSpan.wrap("*") - - "s", "del" -> MarkdownSpan.wrap("~~") - - "code" -> MarkdownSpan.wrap("`") - - "a" -> { - if (tag.getAttributeValue("docref") != null) { - val docRef = tag.getAttributeValue("docref") - val innerText = tag.getValue().getText() - if (docRef == innerText) MarkdownSpan("[", "]") else MarkdownSpan("[", "][$docRef]") - } - else { - MarkdownSpan("[", "](${tag.getAttributeValue("href")})") - } - } - - "ul" -> { currentListType = ListType.Unordered; MarkdownSpan.Empty } - - "ol" -> { currentListType = ListType.Ordered; MarkdownSpan.Empty } - - "li" -> if (currentListType == ListType.Unordered) MarkdownSpan.prefix(" * ") else MarkdownSpan.prefix(" 1. ") - - else -> MarkdownSpan.Empty - } - - private fun appendPendingText() { - if (afterLineBreak ) { - markdownBuilder.append(" * ") - afterLineBreak = false - } - } - - override fun visitXmlFile(file: XmlFile) { - super.visitXmlFile(file) - - markdownBuilder.append(" */") - } - } -} - fun PsiDocTag.content(): String = - getChildren() - .dropWhile { it.getNode().getElementType() == JavaDocTokenType.DOC_TAG_NAME } - .dropWhile { it is PsiWhiteSpace } - .filterNot { it.getNode().getElementType() == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS } - .map { it.getText() } - .join("") + getChildren() + .dropWhile { it.getNode().getElementType() == JavaDocTokenType.DOC_TAG_NAME } + .dropWhile { it is PsiWhiteSpace } + .filterNot { it.getNode().getElementType() == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS } + .map { it.getText() } + .join("") \ No newline at end of file diff --git a/j2k/src/org/jetbrains/kotlin/j2k/ExpressionConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/ExpressionConverter.kt index 0d96fe6abb6..a681b30fbd8 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/ExpressionConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/ExpressionConverter.kt @@ -16,10 +16,12 @@ package org.jetbrains.kotlin.j2k -import com.intellij.codeInsight.generation.GenerateEqualsHelper + +import com.intellij.openapi.project.Project import com.intellij.psi.* import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.tree.IElementType +import com.intellij.psi.util.MethodSignature import com.intellij.psi.util.MethodSignatureUtil import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.KotlinLightField @@ -139,7 +141,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter { if (!psiClass.hasModifierProperty(PsiModifier.FINAL)) return false if (psiClass.isEnum()) return true - val equalsSignature = GenerateEqualsHelper.getEqualsSignature(converter.project, GlobalSearchScope.allScope(converter.project)) + val equalsSignature = getEqualsSignature(converter.project, GlobalSearchScope.allScope(converter.project)) val equalsMethod = MethodSignatureUtil.findMethodBySignature(psiClass, equalsSignature, true) if (equalsMethod != null && equalsMethod.getContainingClass()?.getQualifiedName() != CommonClassNames.JAVA_LANG_OBJECT) return false @@ -151,6 +153,11 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter { } + private fun getEqualsSignature(project: Project, scope: GlobalSearchScope): MethodSignature { + val javaLangObject = PsiType.getJavaLangObject(PsiManager.getInstance(project), scope) + return MethodSignatureUtil.createMethodSignature("equals", arrayOf(javaLangObject), PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY) + } + private val NON_NULL_OPERAND_OPS = setOf( JavaTokenType.ANDAND, JavaTokenType.OROR, diff --git a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt index c93eefbc4e0..dccab623013 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt @@ -16,14 +16,11 @@ package org.jetbrains.kotlin.j2k -import com.intellij.ide.util.DelegatingProgressIndicator import com.intellij.lang.java.JavaLanguage +import com.intellij.openapi.application.ModalityState import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.editor.RangeMarker -import com.intellij.openapi.progress.EmptyProgressIndicator -import com.intellij.openapi.progress.ProcessCanceledException -import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.progress.* import com.intellij.openapi.project.Project import com.intellij.openapi.util.TextRange import com.intellij.psi.* @@ -83,9 +80,7 @@ public enum class ParseContext { public class JavaToKotlinConverter( private val project: Project, private val settings: ConverterSettings, - private val referenceSearcher: ReferenceSearcher, - private val resolverForConverter: ResolverForConverter, - private val docCommentConverter: DocCommentConverter + private val services: JavaToKotlinConverterServices ) { private val LOG = Logger.getInstance("#org.jetbrains.kotlin.j2k.JavaToKotlinConverter") @@ -143,7 +138,7 @@ public class JavaToKotlinConverter( val intermediateResults = processor.processItems(0.25, inputElements) { inputElement -> - Converter.create(inputElement, settings, ::inConversionScope, referenceSearcher, resolverForConverter, docCommentConverter, usageProcessingCollector).convert() + Converter.create(inputElement, settings, ::inConversionScope, services, usageProcessingCollector).convert() }.toArrayList() val results = processor.processItems(0.25, intermediateResults.withIndex()) { pair -> @@ -209,7 +204,7 @@ public class JavaToKotlinConverter( { val searchJava = processings.any { it.javaCodeProcessor != null } val searchKotlin = processings.any { it.kotlinCodeProcessor != null } - referenceSearcher.findUsagesForExternalCodeProcessing(psiElement, searchJava, searchKotlin) + services.referenceSearcher.findUsagesForExternalCodeProcessing(psiElement, searchJava, searchKotlin) .filterNot { inConversionScope(it.getElement()) } .mapTo(refs) { ReferenceInfo(it, psiElement, it.getElement().getContainingFile(), processings) } }, @@ -335,4 +330,63 @@ public class JavaToKotlinConverter( override fun setText2(text: String?) { } } + + // Copied from com.intellij.ide.util.DelegatingProgressIndicator + private open class DelegatingProgressIndicator : WrappedProgressIndicator, StandardProgressIndicator { + protected val delegate: ProgressIndicator + + public constructor(indicator: ProgressIndicator) { + delegate = indicator + } + + public constructor() { + val indicator = ProgressManager.getInstance().progressIndicator + delegate = indicator ?: EmptyProgressIndicator() + } + + override fun start() = delegate.start() + override fun stop() = delegate.stop() + override fun isRunning() = delegate.isRunning + override fun cancel() = delegate.cancel() + override fun isCanceled() = delegate.isCanceled + + override fun setText(text: String?) { + delegate.text = text + } + + override fun getText() = delegate.text + + override fun setText2(text: String?) { + delegate.text2 = text + } + + override fun getText2() = delegate.text2 + override fun getFraction() = delegate.fraction + + override fun setFraction(fraction: Double) { + delegate.fraction = fraction + } + + override fun pushState() = delegate.pushState() + override fun popState() = delegate.popState() + override fun startNonCancelableSection() = delegate.startNonCancelableSection() + override fun finishNonCancelableSection() = delegate.finishNonCancelableSection() + override fun isModal() = delegate.isModal + override fun getModalityState() = delegate.modalityState + + override fun setModalityProgress(modalityProgress: ProgressIndicator) { + delegate.setModalityProgress(modalityProgress) + } + + override fun isIndeterminate() = delegate.isIndeterminate + + override fun setIndeterminate(indeterminate: Boolean) { + delegate.isIndeterminate = indeterminate + } + + override fun checkCanceled() = delegate.checkCanceled() + override fun getOriginalProgressIndicator() = delegate + override fun isPopupWasShown() = delegate.isPopupWasShown + override fun isShowing() = delegate.isShowing + } } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverterServices.kt b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverterServices.kt new file mode 100644 index 00000000000..3721cf37b9d --- /dev/null +++ b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverterServices.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.j2k + +interface JavaToKotlinConverterServices { + val referenceSearcher: ReferenceSearcher + val resolverForConverter: ResolverForConverter + val docCommentConverter: DocCommentConverter +} + +object EmptyJavaToKotlinServices: JavaToKotlinConverterServices { + override val referenceSearcher: ReferenceSearcher + get() = EmptyReferenceSearcher + override val resolverForConverter: ResolverForConverter + get() = EmptyResolverForConverter + override val docCommentConverter: DocCommentConverter + get() = EmptyDocCommentConverter +} \ No newline at end of file diff --git a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinTranslator.kt b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinTranslator.kt index 1b6dccf8cf2..02ab0a60705 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinTranslator.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinTranslator.kt @@ -45,7 +45,7 @@ public object JavaToKotlinTranslator { public fun generateKotlinCode(javaCode: String, project: Project): String { val file = createFile(javaCode, project) if (file is PsiJavaFile) { - val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, EmptyReferenceSearcher, EmptyResolverForConverter, EmptyDocCommentConverter) + val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, EmptyJavaToKotlinServices) return prettify(converter.elementsToKotlin(listOf(file)).results.single()!!.text) //TODO: imports } return "" diff --git a/j2k/src/org/jetbrains/kotlin/j2k/ReferenceSearcher.kt b/j2k/src/org/jetbrains/kotlin/j2k/ReferenceSearcher.kt index 53faa602e8f..19b67d78620 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/ReferenceSearcher.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/ReferenceSearcher.kt @@ -16,16 +16,8 @@ package org.jetbrains.kotlin.j2k -import com.intellij.lang.java.JavaLanguage -import com.intellij.openapi.fileTypes.FileType import com.intellij.psi.* -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.search.LocalSearchScope -import com.intellij.psi.search.searches.ClassInheritorsSearch -import com.intellij.psi.search.searches.OverridingMethodsSearch -import com.intellij.psi.search.searches.ReferencesSearch -import org.jetbrains.kotlin.idea.JetLanguage -import java.util.ArrayList +import com.intellij.psi.util.PsiUtil public interface ReferenceSearcher { fun findLocalUsages(element: PsiElement, scope: PsiElement): Collection @@ -56,24 +48,4 @@ public object EmptyReferenceSearcher: ReferenceSearcher { override fun hasOverrides(method: PsiMethod) = false override fun findUsagesForExternalCodeProcessing(element: PsiElement, searchJava: Boolean, searchKotlin: Boolean): Collection = throw UnsupportedOperationException() -} - -public object IdeaReferenceSearcher: ReferenceSearcher { - override fun findLocalUsages(element: PsiElement, scope: PsiElement) = ReferencesSearch.search(element, LocalSearchScope(scope)).findAll() - - override fun hasInheritors(`class`: PsiClass) = ClassInheritorsSearch.search(`class`, false).any() - - override fun hasOverrides(method: PsiMethod) = OverridingMethodsSearch.search(method, false).any() - - override fun findUsagesForExternalCodeProcessing(element: PsiElement, searchJava: Boolean, searchKotlin: Boolean): Collection { - val fileTypes = ArrayList() - if (searchJava) { - fileTypes.add(JavaLanguage.INSTANCE.getAssociatedFileType()!!) - } - if (searchKotlin) { - fileTypes.add(JetLanguage.INSTANCE.getAssociatedFileType()!!) - } - val searchScope = GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.projectScope(element.getProject()), *fileTypes.toTypedArray()) - return ReferencesSearch.search(element, searchScope).findAll() - } -} +} \ No newline at end of file diff --git a/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt index 2480f41352d..cd738d9a6d3 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt @@ -375,7 +375,7 @@ class TypeConverter(val converter: Converter) { override fun fromAnnotations(owner: PsiModifierListOwner): Mutability { if (owner is KotlinLightElement<*, *>) { val jetDeclaration = owner.getOrigin() as? JetCallableDeclaration ?: return Mutability.Default - val descriptor = converter.resolverForConverter.resolveToDescriptor(jetDeclaration) as? CallableDescriptor ?: return Mutability.Default + val descriptor = converter.services.resolverForConverter.resolveToDescriptor(jetDeclaration) as? CallableDescriptor ?: return Mutability.Default val type = descriptor.getReturnType() ?: return Mutability.Default val classDescriptor = TypeUtils.getClassDescriptor(type) ?: return Mutability.Default return if (DescriptorUtils.getFqName(classDescriptor).asString() in mutableKotlinClasses) diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterMultiFileTest.kt b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterMultiFileTest.kt index a61e61cdca2..aba8f9f7a99 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterMultiFileTest.kt +++ b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterMultiFileTest.kt @@ -21,6 +21,7 @@ import com.intellij.psi.PsiFile import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager import com.intellij.testFramework.LightPlatformTestCase +import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.idea.test.JetWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor @@ -54,7 +55,7 @@ public abstract class AbstractJavaToKotlinConverterMultiFileTest : AbstractJavaT assert(psiFile is PsiJavaFile || psiFile is JetFile) } - val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaReferenceSearcher, IdeaResolverForConverter, EmptyDocCommentConverter) + val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices) val (results, externalCodeProcessor) = converter.filesToKotlin(psiFilesToConvert, J2kPostProcessor(formatCode = true)) val process = externalCodeProcessor?.prepareWriteOperation(EmptyProgressIndicator()) diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt index e1249bbeb87..555f7c566a0 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt +++ b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.test.util.trimIndent import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor import org.jetbrains.kotlin.idea.test.JetWithJdkAndRuntimeLightProjectDescriptor import com.intellij.psi.PsiJavaFile +import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter import org.jetbrains.kotlin.idea.test.dumpTextWithErrors @@ -107,8 +108,7 @@ public abstract class AbstractJavaToKotlinConverterSingleFileTest : AbstractJava private fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String { val file = createJavaFile(text) - val converter = JavaToKotlinConverter(project, settings, - IdeaReferenceSearcher, IdeaResolverForConverter, IdeaDocCommentConverter) + val converter = JavaToKotlinConverter(project, settings, IdeaJavaToKotlinServices) return converter.filesToKotlin(listOf(file), J2kPostProcessor(formatCode = true)).results.single() }