J2K: conversion with usage processing across multiple converted files works in tests (but not in real life yet)

This commit is contained in:
Valentin Kipyatkov
2014-10-20 22:34:22 +04:00
committed by valentin
parent 41c7ec8285
commit abf537e348
1111 changed files with 1904 additions and 1625 deletions
@@ -113,7 +113,7 @@ import org.jetbrains.jet.plugin.stubs.AbstractLazyResolveByStubTest
import org.jetbrains.jet.plugin.stubs.AbstractMultiFileHighlightingTest import org.jetbrains.jet.plugin.stubs.AbstractMultiFileHighlightingTest
import org.jetbrains.jet.cfg.AbstractPseudoValueTest import org.jetbrains.jet.cfg.AbstractPseudoValueTest
import org.jetbrains.jet.plugin.structureView.AbstractKotlinFileStructureTest import org.jetbrains.jet.plugin.structureView.AbstractKotlinFileStructureTest
import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterSingleFileTest
import org.jetbrains.jet.jps.build.AbstractIncrementalJpsTest import org.jetbrains.jet.jps.build.AbstractIncrementalJpsTest
import org.jetbrains.jet.asJava.AbstractKotlinLightClassTest import org.jetbrains.jet.asJava.AbstractKotlinLightClassTest
import org.jetbrains.jet.lang.resolve.java.AbstractJavaTypeSubstitutorTest import org.jetbrains.jet.lang.resolve.java.AbstractJavaTypeSubstitutorTest
@@ -127,6 +127,7 @@ import org.jetbrains.jet.generators.tests.reservedWords.generateTestDataForReser
import org.jetbrains.k2js.test.semantics.AbstractReservedWordTest import org.jetbrains.k2js.test.semantics.AbstractReservedWordTest
import org.jetbrains.jet.resolve.AbstractReferenceResolveInJavaTest import org.jetbrains.jet.resolve.AbstractReferenceResolveInJavaTest
import org.jetbrains.k2js.test.semantics.AbstractBridgeTest import org.jetbrains.k2js.test.semantics.AbstractBridgeTest
import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterMultiFileTest
import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterForWebDemoTest import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterForWebDemoTest
fun main(args: Array<String>) { fun main(args: Array<String>) {
@@ -629,14 +630,18 @@ fun main(args: Array<String>) {
} }
testGroup("j2k/tests/test", "j2k/tests/testData") { testGroup("j2k/tests/test", "j2k/tests/testData") {
testClass(javaClass<AbstractJavaToKotlinConverterTest>()) { testClass(javaClass<AbstractJavaToKotlinConverterSingleFileTest>()) {
model("ast", extension = "java") model("fileOrElement", extension = "java")
} }
} }
testGroup("j2k/tests/test", "j2k/tests/testData") { testGroup("j2k/tests/test", "j2k/tests/testData") {
testClass(javaClass<AbstractJavaToKotlinConverterForWebDemoTest>()) { testClass(javaClass<AbstractJavaToKotlinConverterMultiFileTest>()) {
model("ast", extension = "java") model("multiFile", extension = null)
}
}
testGroup("j2k/tests/test", "j2k/tests/testData") {
testClass(javaClass<AbstractJavaToKotlinConverterForWebDemoTest>()) {
model("fileOrElement", extension = "java")
} }
} }
@@ -25,8 +25,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiJavaFile; import com.intellij.psi.PsiJavaFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.j2k.*; import org.jetbrains.jet.j2k.ConverterSettings;
import org.jetbrains.jet.plugin.j2k.J2kPostProcessor; import org.jetbrains.jet.j2k.FilesConversionScope;
import org.jetbrains.jet.j2k.IdeaReferenceSearcher;
import org.jetbrains.jet.j2k.JavaToKotlinConverter;
import java.util.List; import java.util.List;
@@ -47,9 +49,7 @@ public class JavaToKotlinAction extends AnAction {
final JavaToKotlinConverter converter = new JavaToKotlinConverter(project, final JavaToKotlinConverter converter = new JavaToKotlinConverter(project,
ConverterSettings.defaultSettings, ConverterSettings.defaultSettings,
new FilesConversionScope(selectedJavaFiles), new FilesConversionScope(selectedJavaFiles),
IdeaReferenceSearcher.INSTANCE$, IdeaReferenceSearcher.INSTANCE$);
//TODO: (module refactoring) resulting files should be analyzed in context of respective java files
new J2kPostProcessor(selectedJavaFiles.iterator().next()));
CommandProcessor.getInstance().executeCommand( CommandProcessor.getInstance().executeCommand(
project, project,
new Runnable() { new Runnable() {
@@ -21,13 +21,17 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ex.MessagesEx; import com.intellij.openapi.ui.ex.MessagesEx;
import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile; import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiManager; import com.intellij.psi.PsiManager;
import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.CodeStyleManager;
import kotlin.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.j2k.JavaToKotlinConverter; import org.jetbrains.jet.j2k.JavaToKotlinConverter;
import org.jetbrains.jet.j2k.PostProcessor;
import org.jetbrains.jet.plugin.j2k.J2kPostProcessor;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
@@ -124,7 +128,8 @@ public class JavaToKotlinActionUtil {
try { try {
VirtualFile virtualFile = psiFile.getVirtualFile(); VirtualFile virtualFile = psiFile.getVirtualFile();
if (psiFile instanceof PsiJavaFile && virtualFile != null) { if (psiFile instanceof PsiJavaFile && virtualFile != null) {
String result = converter.elementToKotlin(psiFile); J2kPostProcessor postProcessor = new J2kPostProcessor(psiFile);
String result = converter.elementsToKotlin(new Pair<PsiElement, PostProcessor>(psiFile, postProcessor)).get(0); //TODO: convert all files in one call!
PsiManager manager = psiFile.getManager(); PsiManager manager = psiFile.getManager();
assert manager != null; assert manager != null;
VirtualFile copy = virtualFile.copy(manager, virtualFile.getParent(), virtualFile.getNameWithoutExtension() + ".kt"); VirtualFile copy = virtualFile.copy(manager, virtualFile.getParent(), virtualFile.getNameWithoutExtension() + ".kt");
@@ -32,8 +32,8 @@ import org.jetbrains.jet.plugin.editor.JetEditorOptions
import java.awt.datatransfer.Transferable import java.awt.datatransfer.Transferable
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.codeStyle.CodeStyleManager
import org.jetbrains.jet.plugin.j2k.J2kPostProcessor;
import com.intellij.lang.java.JavaLanguage import com.intellij.lang.java.JavaLanguage
import org.jetbrains.jet.plugin.j2k.J2kPostProcessor
public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTransferableData>() { public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBlockTransferableData>() {
@@ -89,8 +89,7 @@ public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBl
val converter = JavaToKotlinConverter(fileCopiedFrom.getProject(), val converter = JavaToKotlinConverter(fileCopiedFrom.getProject(),
ConverterSettings.defaultSettings, ConverterSettings.defaultSettings,
FilesConversionScope(listOf(fileCopiedFrom)), FilesConversionScope(listOf(fileCopiedFrom)),
IdeaReferenceSearcher, IdeaReferenceSearcher)
J2kPostProcessor(fileCopiedTo))
val startOffsets = code.startOffsets val startOffsets = code.startOffsets
val endOffsets = code.endOffsets val endOffsets = code.endOffsets
assert(startOffsets.size == endOffsets.size) { "Must have the same size" } assert(startOffsets.size == endOffsets.size) { "Must have the same size" }
@@ -98,12 +97,13 @@ public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBl
for (i in startOffsets.indices) { for (i in startOffsets.indices) {
val startOffset = startOffsets[i] val startOffset = startOffsets[i]
val endOffset = endOffsets[i] val endOffset = endOffsets[i]
result.append(convertRangeToKotlin(fileCopiedFrom, TextRange(startOffset, endOffset), converter)) result.append(convertRangeToKotlin(fileCopiedFrom, fileCopiedTo, TextRange(startOffset, endOffset), converter))
} }
return StringUtil.convertLineSeparators(result.toString()) return StringUtil.convertLineSeparators(result.toString())
} }
private fun convertRangeToKotlin(file: PsiJavaFile, private fun convertRangeToKotlin(file: PsiJavaFile,
fileCopiedTo: JetFile,
range: TextRange, range: TextRange,
converter: JavaToKotlinConverter): String { converter: JavaToKotlinConverter): String {
val result = StringBuilder() val result = StringBuilder()
@@ -120,7 +120,7 @@ public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor<TextBl
val elementToConvert = findTopMostParentWhollyInRange(currentRange, leafElement) val elementToConvert = findTopMostParentWhollyInRange(currentRange, leafElement)
val unconvertedPrefix = fileText.substring(currentRange.start, elementToConvert.range.start) val unconvertedPrefix = fileText.substring(currentRange.start, elementToConvert.range.start)
result.append(unconvertedPrefix) result.append(unconvertedPrefix)
val converted = converter.elementToKotlin(elementToConvert) val converted = converter.elementsToKotlin(elementToConvert to J2kPostProcessor(fileCopiedTo))[0]
if (converted.isNotEmpty()) { if (converted.isNotEmpty()) {
result.append(converted) result.append(converted)
} }
+20 -5
View File
@@ -72,7 +72,25 @@ class Converter private(private val elementToConvert: PsiElement,
private fun createDefaultCodeConverter() = CodeConverter(this, DefaultExpressionConverter(), DefaultStatementConverter(), null) private fun createDefaultCodeConverter() = CodeConverter(this, DefaultExpressionConverter(), DefaultStatementConverter(), null)
public fun convert(): Element? = convertTopElement(elementToConvert) public trait IntermediateResult {
fun finishConversion(usageProcessings: Collection<UsageProcessing>): String
val usageProcessings: Collection<UsageProcessing>
}
public fun convert(): IntermediateResult? {
val element = convertTopElement(elementToConvert) ?: return null
return object: IntermediateResult {
override fun finishConversion(usageProcessings: Collection<UsageProcessing>): String {
unfoldLazyElements(usageProcessings)
val builder = CodeBuilder(elementToConvert)
builder.append(element)
return builder.result
}
override val usageProcessings: Collection<UsageProcessing> = commonState.usageProcessings
}
}
private fun convertTopElement(element: PsiElement): Element? = when (element) { private fun convertTopElement(element: PsiElement): Element? = when (element) {
is PsiJavaFile -> convertFile(element) is PsiJavaFile -> convertFile(element)
@@ -88,10 +106,7 @@ class Converter private(private val elementToConvert: PsiElement,
else -> null else -> null
} }
public val usageProcessings: Collection<UsageProcessing> private fun unfoldLazyElements(usageProcessings: Collection<UsageProcessing>) {
get() = commonState.usageProcessings
public fun unfoldLazyElements(usageProcessings: Collection<UsageProcessing>) {
val codeConverter = createDefaultCodeConverter().withSpecialExpressionConverter(UsageProcessingExpressionConverter(usageProcessings)) val codeConverter = createDefaultCodeConverter().withSpecialExpressionConverter(UsageProcessingExpressionConverter(usageProcessings))
// we use loop with index because new lazy elements can be added during unfolding // we use loop with index because new lazy elements can be added during unfolding
@@ -24,7 +24,8 @@ import com.intellij.psi.PsiJavaFile
import org.jetbrains.jet.lang.psi.JetFile import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.lang.resolve.BindingContext
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.jet.j2k.usageProcessing.UsageProcessingExpressionConverter import java.util.ArrayList
import org.jetbrains.jet.j2k.usageProcessing.UsageProcessing
public trait ConversionScope { public trait ConversionScope {
public fun contains(element: PsiElement): Boolean public fun contains(element: PsiElement): Boolean
@@ -42,43 +43,52 @@ public trait PostProcessor {
public class JavaToKotlinConverter(private val project: Project, public class JavaToKotlinConverter(private val project: Project,
private val settings: ConverterSettings, private val settings: ConverterSettings,
private val conversionScope: ConversionScope, private val conversionScope: ConversionScope /*TODO: drop this parameter*/,
private val referenceSearcher: ReferenceSearcher, private val referenceSearcher: ReferenceSearcher) {
private val postProcessor: PostProcessor?) {
private val LOG = Logger.getInstance("#org.jetbrains.jet.j2k.JavaToKotlinConverter") private val LOG = Logger.getInstance("#org.jetbrains.jet.j2k.JavaToKotlinConverter")
//TODO: run not for one element when multiple files public fun elementsToKotlin(vararg psiElementsAndProcessors: Pair<PsiElement, PostProcessor?>): List<String> {
public fun elementToKotlin(psiElement: PsiElement): String {
try { try {
val converter = Converter.create(psiElement, settings, conversionScope, referenceSearcher, postProcessor) val intermediateResults = ArrayList<Converter.IntermediateResult?>(psiElementsAndProcessors.size)
val element = converter.convert() ?: return "" val usageProcessings = ArrayList<UsageProcessing>()
for ((psiElement, postProcessor) in psiElementsAndProcessors) {
val converter = Converter.create(psiElement, settings, conversionScope, referenceSearcher, postProcessor)
val result = converter.convert()
intermediateResults.add(result)
result?.usageProcessings?.let { usageProcessings.addAll(it) }
}
converter.unfoldLazyElements(converter.usageProcessings) val results = ArrayList<String>(psiElementsAndProcessors.size)
for (result in intermediateResults) {
results.add(result?.finishConversion(usageProcessings) ?: "")
}
val builder = CodeBuilder(psiElement) val finalResults = ArrayList<String>(psiElementsAndProcessors.size)
builder.append(element) for ((i, result) in results.withIndices()) {
val postProcessor = psiElementsAndProcessors[i].second
if (postProcessor != null) { if (postProcessor != null) {
try { try {
return AfterConversionPass(project, postProcessor).run(builder.result) finalResults.add(AfterConversionPass(project, postProcessor).run(result))
}
catch(e: ProcessCanceledException) {
throw e
}
catch(t: Throwable) {
LOG.error(t)
finalResults.add(result)
}
} }
catch(e: ProcessCanceledException) { else {
throw e finalResults.add(result)
}
catch(t: Throwable) {
LOG.error(t)
return builder.result
} }
} }
else { return finalResults
return builder.result
}
} }
catch(e: ElementCreationStackTraceRequiredException) { catch(e: ElementCreationStackTraceRequiredException) {
// if we got this exception then we need to turn element creation stack traces on to get better diagnostic // if we got this exception then we need to turn element creation stack traces on to get better diagnostic
Element.saveCreationStacktraces = true Element.saveCreationStacktraces = true
try { try {
return elementToKotlin(psiElement) return elementsToKotlin(*psiElementsAndProcessors)
} }
finally { finally {
Element.saveCreationStacktraces = false Element.saveCreationStacktraces = false
@@ -90,8 +90,8 @@ public object JavaToKotlinTranslator {
fun generateKotlinCode(javaCode: String): String { fun generateKotlinCode(javaCode: String): String {
val file = createFile(javaCode) val file = createFile(javaCode)
if (file is PsiJavaFile) { if (file is PsiJavaFile) {
val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, FilesConversionScope(listOf(file)), EmptyReferenceSearcher, null) val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, FilesConversionScope(listOf(file)), EmptyReferenceSearcher)
return prettify(converter.elementToKotlin(file)) return prettify(converter.elementsToKotlin(file to null)[0])
} }
return "" return ""
} }
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2014 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.jet.j2k.test
import java.io.File
import com.intellij.testFramework.LightPlatformTestCase
import com.intellij.psi.codeStyle.CodeStyleManager
import org.jetbrains.jet.JetTestUtils
import com.intellij.openapi.project.Project
import com.intellij.openapi.command.WriteCommandAction
import org.jetbrains.jet.j2k.FilesConversionScope
import org.jetbrains.jet.plugin.j2k.J2kPostProcessor
import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor
import com.intellij.psi.PsiJavaFile
import org.jetbrains.jet.j2k.IdeaReferenceSearcher
import org.jetbrains.jet.j2k.JavaToKotlinConverter
import com.intellij.psi.PsiManager
import java.util.ArrayList
import org.jetbrains.jet.j2k.ConverterSettings
public abstract class AbstractJavaToKotlinConverterMultiFileTest() : AbstractJavaToKotlinConverterTest() {
public fun doTest(dirPath: String) {
val project = LightPlatformTestCase.getProject()!!
val javaFiles = File(dirPath).listFiles {(file, name): Boolean -> name.endsWith(".java") }
val psiFiles = ArrayList<PsiJavaFile>()
for (javaFile: File in javaFiles) {
val virtualFile = addFile(javaFile, "test")
val psiFile = PsiManager.getInstance(project).findFile(virtualFile) as PsiJavaFile
psiFiles.add(psiFile)
}
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, FilesConversionScope(psiFiles), IdeaReferenceSearcher)
val results: List<String> = converter.elementsToKotlin(*psiFiles.map { it to J2kPostProcessor(it) }.copyToArray())
.map { reformat(it, project) }
for ((i, javaFile) in javaFiles.withIndices()) {
val kotlinPath = javaFile.getPath().replace(".java", ".kt")
val expectedFile = File(kotlinPath)
JetTestUtils.assertEqualsToFile(expectedFile, results[i])
}
}
private fun reformat(text: String, project: Project): String {
val convertedFile = JetTestUtils.createFile("converted", text, project)
WriteCommandAction.runWriteCommandAction(project) {
CodeStyleManager.getInstance(project)!!.reformat(convertedFile)
}
return convertedFile.getText()!!
}
override fun getProjectDescriptor()
= JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
}
@@ -0,0 +1,149 @@
/*
* Copyright 2010-2014 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.jet.j2k.test
import java.io.File
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.jet.j2k.ConverterSettings
import java.util.regex.Pattern
import com.intellij.testFramework.LightPlatformTestCase
import com.intellij.psi.codeStyle.CodeStyleManager
import org.jetbrains.jet.JetTestUtils
import com.intellij.openapi.project.Project
import com.intellij.openapi.command.WriteCommandAction
import org.jetbrains.jet.test.util.trimIndent
import org.jetbrains.jet.j2k.FilesConversionScope
import org.jetbrains.jet.plugin.j2k.J2kPostProcessor
import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor
import com.intellij.psi.PsiJavaFile
import org.jetbrains.jet.j2k.IdeaReferenceSearcher
import org.jetbrains.jet.j2k.JavaToKotlinConverter
public abstract class AbstractJavaToKotlinConverterSingleFileTest() : AbstractJavaToKotlinConverterTest() {
val testHeaderPattern = Pattern.compile("//(element|expression|statement|method|class|file|comp)\n")
public fun doTest(javaPath: String) {
val project = LightPlatformTestCase.getProject()!!
val javaFile = File(javaPath)
val fileContents = FileUtil.loadFile(javaFile, true)
val matcher = testHeaderPattern.matcher(fileContents)
val (prefix, javaCode) = if (matcher.find()) {
Pair(matcher.group().trim().substring(2), matcher.replaceFirst(""))
}
else {
Pair("file", fileContents)
}
fun parseBoolean(text: String): Boolean = when (text) {
"true" -> true
"false" -> false
else -> throw IllegalArgumentException("Unknown option value: $text")
}
var settings = ConverterSettings.defaultSettings.copy()
val directives = JetTestUtils.parseDirectives(javaCode)
for ((name, value) in directives) {
when (name) {
"forceNotNullTypes" -> settings.forceNotNullTypes = parseBoolean(value)
"specifyLocalVariableTypeByDefault" -> settings.specifyLocalVariableTypeByDefault = parseBoolean(value)
"specifyFieldTypeByDefault" -> settings.specifyFieldTypeByDefault = parseBoolean(value)
"openByDefault" -> settings.openByDefault = parseBoolean(value)
else -> throw IllegalArgumentException("Unknown option: $name")
}
}
val rawConverted = when (prefix) {
"element" -> elementToKotlin(javaCode, settings, project)
"expression" -> expressionToKotlin(javaCode, settings, project)
"statement" -> statementToKotlin(javaCode, settings, project)
"method" -> methodToKotlin(javaCode, settings, project)
"class" -> fileToKotlin(javaCode, settings, project)
"file" -> fileToKotlin(javaCode, settings, project)
else -> throw IllegalStateException("Specify what is it: file, class, method, statement or expression " +
"using the first line of test data file")
}
val reformatInFun = prefix in setOf("element", "expression", "statement")
val actual = reformat(rawConverted, project, reformatInFun)
val kotlinPath = javaPath.replace(".java", ".kt")
val expectedFile = File(kotlinPath)
JetTestUtils.assertEqualsToFile(expectedFile, actual)
}
private fun reformat(text: String, project: Project, inFunContext: Boolean): String {
val textToFormat = if (inFunContext) "fun convertedTemp() {\n$text\n}" else text
val convertedFile = JetTestUtils.createFile("converted", textToFormat, project)
WriteCommandAction.runWriteCommandAction(project) {
CodeStyleManager.getInstance(project)!!.reformat(convertedFile)
}
val reformattedText = convertedFile.getText()!!
return if (inFunContext)
reformattedText.removeFirstLine().removeLastLine().trimIndent()
else
reformattedText
}
private fun elementToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val fileWithText = createJavaFile(text)
val converter = JavaToKotlinConverter(project, settings, FilesConversionScope(listOf(fileWithText)), IdeaReferenceSearcher)
val element = fileWithText.getFirstChild()!!
return converter.elementsToKotlin(element to J2kPostProcessor(fileWithText))[0]
}
private fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val file = createJavaFile(text)
val converter = JavaToKotlinConverter(project, settings, FilesConversionScope(listOf(file)), IdeaReferenceSearcher)
return converter.elementsToKotlin(file to J2kPostProcessor(file))[0]
}
private fun methodToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val result = fileToKotlin("final class C {" + text + "}", settings, project).replaceAll("class C \\{", "")
return result.substring(0, (result.lastIndexOf("}"))).trim()
}
private fun statementToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val result = methodToKotlin("void main() {" + text + "}", settings, project)
return result.substring(0, result.lastIndexOf("}")).replaceFirst("fun main\\(\\) \\{", "").trim()
}
private fun expressionToKotlin(code: String, settings: ConverterSettings, project: Project): String {
val result = statementToKotlin("final Object o =" + code + "}", settings, project)
return result.replaceFirst("val o:Any\\? = ", "").replaceFirst("val o:Any = ", "").replaceFirst("val o = ", "").trim()
}
override fun getProjectDescriptor()
= JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
private fun String.removeFirstLine(): String {
val lastNewLine = indexOf('\n')
return if (lastNewLine == -1) "" else substring(lastNewLine)
}
private fun String.removeLastLine(): String {
val lastNewLine = lastIndexOf('\n')
return if (lastNewLine == -1) "" else substring(0, lastNewLine)
}
private fun createJavaFile(text: String): PsiJavaFile {
return myFixture.configureByText("converterTestFile.java", text) as PsiJavaFile
}
}
@@ -16,169 +16,51 @@
package org.jetbrains.jet.j2k.test package org.jetbrains.jet.j2k.test
import java.io.File
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.jet.j2k.ConverterSettings import java.io.File
import java.util.regex.Pattern
import com.intellij.testFramework.LightPlatformTestCase import com.intellij.testFramework.LightPlatformTestCase
import com.intellij.psi.codeStyle.CodeStyleManager
import org.jetbrains.jet.JetTestUtils
import com.intellij.openapi.project.Project
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import org.jetbrains.jet.test.util.trimIndent
import org.jetbrains.jet.j2k.FilesConversionScope
import org.jetbrains.jet.plugin.j2k.J2kPostProcessor
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaFile import com.intellij.openapi.util.Computable
import org.jetbrains.jet.j2k.IdeaReferenceSearcher
import junit.framework.TestCase import junit.framework.TestCase
import org.jetbrains.jet.j2k.translateToKotlin import org.jetbrains.jet.j2k.translateToKotlin
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import org.jetbrains.jet.JetTestCaseBuilder
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import org.jetbrains.jet.j2k.JavaToKotlinConverter
import org.jetbrains.jet.j2k.JavaToKotlinTranslator import org.jetbrains.jet.j2k.JavaToKotlinTranslator
import org.jetbrains.jet.JetTestCaseBuilder
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
public abstract class AbstractJavaToKotlinConverterTest() : LightCodeInsightFixtureTestCase() { public abstract class AbstractJavaToKotlinConverterTest : LightCodeInsightFixtureTestCase() {
val testHeaderPattern = Pattern.compile("//(element|expression|statement|method|class|file|comp)\n")
override fun setUp() { override fun setUp() {
super.setUp() super.setUp()
VfsRootAccess.allowRootAccess(JetTestCaseBuilder.getHomeDirectory()) VfsRootAccess.allowRootAccess(JetTestCaseBuilder.getHomeDirectory())
fun addFile(fileName: String, packageName: String) { addFile("KotlinApi.kt", "kotlinApi")
val code = FileUtil.loadFile(File("j2k/tests/testData/$fileName"), true) addFile("JavaApi.java", "javaApi")
val root = LightPlatformTestCase.getSourceRoot()!!
val dir = root.findChild(packageName) ?: root.createChildDirectory(null, packageName)
val file = dir.createChildData(null, fileName)!!
file.getOutputStream(null)!!.writer().use { it.write(code) }
}
ApplicationManager.getApplication()!!.runWriteAction{
addFile("KotlinApi.kt", "kotlinApi")
addFile("JavaApi.java", "javaApi")
}
} }
override fun tearDown() { override fun tearDown() {
VfsRootAccess.disallowRootAccess(JetTestCaseBuilder.getHomeDirectory()) VfsRootAccess.disallowRootAccess(JetTestCaseBuilder.getHomeDirectory())
super<LightCodeInsightFixtureTestCase>.tearDown() super.tearDown()
}
private fun addFile(fileName: String, packageName: String) {
addFile(File("j2k/tests/testData/$fileName"), packageName)
} }
public fun doTest(javaPath: String) { fun addFile(file: File, packageName: String): VirtualFile {
val project = LightPlatformTestCase.getProject()!! return ApplicationManager.getApplication()!!.runWriteAction(object: Computable<VirtualFile> {
val javaFile = File(javaPath) override fun compute(): VirtualFile? {
val fileContents = FileUtil.loadFile(javaFile, true) val code = FileUtil.loadFile(file, true)
val matcher = testHeaderPattern.matcher(fileContents) val root = LightPlatformTestCase.getSourceRoot()!!
val virtualDir = root.findChild(packageName) ?: root.createChildDirectory(null, packageName)
val (prefix, javaCode) = if (matcher.find()) { val virtualFile = virtualDir.createChildData(null, file.getName())!!
Pair(matcher.group().trim().substring(2), matcher.replaceFirst("")) virtualFile.getOutputStream(null)!!.writer().use { it.write(code) }
} return virtualFile
else {
Pair("file", fileContents)
}
fun parseBoolean(text: String): Boolean = when (text) {
"true" -> true
"false" -> false
else -> throw IllegalArgumentException("Unknown option value: $text")
}
var settings = ConverterSettings.defaultSettings.copy()
val directives = JetTestUtils.parseDirectives(javaCode)
for ((name, value) in directives) {
when (name) {
"forceNotNullTypes" -> settings.forceNotNullTypes = parseBoolean(value)
"specifyLocalVariableTypeByDefault" -> settings.specifyLocalVariableTypeByDefault = parseBoolean(value)
"specifyFieldTypeByDefault" -> settings.specifyFieldTypeByDefault = parseBoolean(value)
"openByDefault" -> settings.openByDefault = parseBoolean(value)
else -> throw IllegalArgumentException("Unknown option: $name")
} }
} })
val rawConverted = when (prefix) {
"element" -> elementToKotlin(javaCode, settings, project)
"expression" -> expressionToKotlin(javaCode, settings, project)
"statement" -> statementToKotlin(javaCode, settings, project)
"method" -> methodToKotlin(javaCode, settings, project)
"class" -> fileToKotlin(javaCode, settings, project)
"file" -> fileToKotlin(javaCode, settings, project)
else -> throw IllegalStateException("Specify what is it: file, class, method, statement or expression " +
"using the first line of test data file")
}
val reformatInFun = prefix in setOf("element", "expression", "statement")
val actual = reformat(rawConverted, project, reformatInFun)
val kotlinPath = javaPath.replace(".java", ".kt")
val expectedFile = File(kotlinPath)
JetTestUtils.assertEqualsToFile(expectedFile, actual)
} }
private fun reformat(text: String, project: Project, inFunContext: Boolean): String {
val textToFormat = if (inFunContext) "fun convertedTemp() {\n$text\n}" else text
val convertedFile = JetTestUtils.createFile("converted", textToFormat, project)
WriteCommandAction.runWriteCommandAction(project) {
CodeStyleManager.getInstance(project)!!.reformat(convertedFile)
}
val reformattedText = convertedFile.getText()!!
return if (inFunContext)
reformattedText.removeFirstLine().removeLastLine().trimIndent()
else
reformattedText
}
private fun elementToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val fileWithText = createJavaFile(text)
val converter = JavaToKotlinConverter(project, settings, FilesConversionScope(listOf(fileWithText)), IdeaReferenceSearcher, J2kPostProcessor(fileWithText))
val element = fileWithText.getFirstChild()!!
return converter.elementToKotlin(element)
}
private fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val file = createJavaFile(text)
val converter = JavaToKotlinConverter(project, settings, FilesConversionScope(listOf(file)), IdeaReferenceSearcher, J2kPostProcessor(file))
return converter.elementToKotlin(file)
}
private fun methodToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val result = fileToKotlin("final class C {" + text + "}", settings, project).replaceAll("class C \\{", "")
return result.substring(0, (result.lastIndexOf("}"))).trim()
}
private fun statementToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val result = methodToKotlin("void main() {" + text + "}", settings, project)
return result.substring(0, result.lastIndexOf("}")).replaceFirst("fun main\\(\\) \\{", "").trim()
}
private fun expressionToKotlin(code: String, settings: ConverterSettings, project: Project): String {
val result = statementToKotlin("final Object o =" + code + "}", settings, project)
return result.replaceFirst("val o:Any\\? = ", "").replaceFirst("val o:Any = ", "").replaceFirst("val o = ", "").trim()
}
override fun getProjectDescriptor()
= JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
private fun String.removeFirstLine(): String {
val lastNewLine = indexOf('\n')
return if (lastNewLine == -1) "" else substring(lastNewLine)
}
private fun String.removeLastLine(): String {
val lastNewLine = lastIndexOf('\n')
return if (lastNewLine == -1) "" else substring(0, lastNewLine)
}
private fun createJavaFile(text: String): PsiJavaFile {
return myFixture.configureByText("converterTestFile.java", text) as PsiJavaFile
}
} }
public abstract class AbstractJavaToKotlinConverterForWebDemoTest() : TestCase() { public abstract class AbstractJavaToKotlinConverterForWebDemoTest() : TestCase() {
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2014 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.jet.j2k.test;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.jet.JUnit3RunnerWithInners;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.InnerTestClasses;
import org.jetbrains.jet.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("j2k/tests/testData/multiFile")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({})
@RunWith(JUnit3RunnerWithInners.class)
public class JavaToKotlinConverterMultiFileTestGenerated extends AbstractJavaToKotlinConverterMultiFileTest {
public void testAllFilesPresentInMultiFile() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/tests/testData/multiFile"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("GetterAndSetterUsages")
public void testGetterAndSetterUsages() throws Exception {
String fileName = JetTestUtils.navigationMetadata("j2k/tests/testData/multiFile/GetterAndSetterUsages/");
doTest(fileName);
}
}

Some files were not shown because too many files have changed in this diff Show More