diff --git a/plugins/android-compiler-plugin/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor b/plugins/android-compiler-plugin/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor index c4157769bcd..a636bdf19ba 100644 --- a/plugins/android-compiler-plugin/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor +++ b/plugins/android-compiler-plugin/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor @@ -1 +1 @@ -org.jetbrains.kotlin.android.AndroidCommandLineProcessor \ No newline at end of file +org.jetbrains.kotlin.android.synthetic.AndroidCommandLineProcessor \ No newline at end of file diff --git a/plugins/android-compiler-plugin/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar b/plugins/android-compiler-plugin/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar index 51108826467..9b3c33f0f80 100644 --- a/plugins/android-compiler-plugin/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +++ b/plugins/android-compiler-plugin/src/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar @@ -1 +1 @@ -org.jetbrains.kotlin.android.AndroidComponentRegistrar \ No newline at end of file +org.jetbrains.kotlin.android.synthetic.AndroidComponentRegistrar \ No newline at end of file diff --git a/plugins/android-compiler-plugin/src/AndroidComponentRegistrar.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt similarity index 82% rename from plugins/android-compiler-plugin/src/AndroidComponentRegistrar.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt index 7ed48ec76b8..9a2b4dd1682 100644 --- a/plugins/android-compiler-plugin/src/AndroidComponentRegistrar.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt @@ -14,14 +14,13 @@ * limitations under the License. */ -package org.jetbrains.kotlin.android +package org.jetbrains.kotlin.android.synthetic import com.intellij.mock.MockProject import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.project.Project -import com.intellij.psi.impl.PsiTreeChangePreprocessor import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.android.synthetic.codegen.AndroidExpressionCodegenExtension import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension import org.jetbrains.kotlin.compiler.plugin.CliOption import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException @@ -30,7 +29,10 @@ import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfigurationKey import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider -import org.jetbrains.kotlin.lang.resolve.android.* +import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager +import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator +import org.jetbrains.kotlin.android.synthetic.res.CliAndroidLayoutXmlFileManager +import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator import org.jetbrains.kotlin.psi.JetFile public object AndroidConfigurationKeys { @@ -68,8 +70,8 @@ public class AndroidCommandLineProcessor : CommandLineProcessor { public class CliAndroidDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider { override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection { - val parser = ServiceManager.getService(project, javaClass()) - return parser.parseToPsi() ?: listOf() + val parser = ServiceManager.getService(project, javaClass()) + return parser.getSyntheticFiles() ?: listOf() } } @@ -81,11 +83,10 @@ public class AndroidComponentRegistrar : ComponentRegistrar { val supportV4 = configuration.get(AndroidConfigurationKeys.SUPPORT_V4) ?: "false" if (androidResPath != null && androidManifest != null) { - val xmlProcessor = CliAndroidUIXmlProcessor(project, androidManifest, androidResPath) - if (supportV4 == "true") xmlProcessor.supportV4 = true + val xmlProcessor = CliSyntheticFileGenerator(project, androidManifest, androidResPath, supportV4 == "true") - project.registerService(javaClass(), xmlProcessor) - project.registerService(javaClass(), CliAndroidResourceManager(project, androidManifest, androidResPath)) + project.registerService(javaClass(), xmlProcessor) + project.registerService(javaClass(), CliAndroidLayoutXmlFileManager(project, androidManifest, androidResPath)) ExternalDeclarationsProvider.registerExtension(project, CliAndroidDeclarationsProvider(project)) ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegenExtension()) diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidConst.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidConst.kt similarity index 92% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidConst.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidConst.kt index 08ae8908efb..e6928660ec5 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidConst.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidConst.kt @@ -14,9 +14,12 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic import com.intellij.openapi.util.Key +import org.jetbrains.kotlin.android.synthetic.res.AndroidFragment +import org.jetbrains.kotlin.android.synthetic.res.AndroidResource +import org.jetbrains.kotlin.android.synthetic.res.AndroidWidget import org.jetbrains.kotlin.lexer.JetKeywordToken import org.jetbrains.kotlin.lexer.JetTokens diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidUtil.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidUtil.kt similarity index 77% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidUtil.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidUtil.kt index 03b5bb22db4..811146539a7 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidUtil.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidUtil.kt @@ -14,17 +14,12 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiElement -import com.intellij.openapi.project.Project -import com.intellij.openapi.components.ServiceManager -import com.intellij.psi.PsiField -import com.intellij.psi.PsiClass import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.util.Computable -import com.intellij.openapi.module.ModuleServiceManager +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile fun isAndroidSyntheticFile(f: PsiFile?): Boolean { return f?.getUserData(AndroidConst.ANDROID_USER_PACKAGE) != null @@ -32,6 +27,6 @@ fun isAndroidSyntheticFile(f: PsiFile?): Boolean { public fun isAndroidSyntheticElement(element: PsiElement?): Boolean { return isAndroidSyntheticFile(ApplicationManager.getApplication().runReadAction(Computable { - element?.getContainingFile() + element?.containingFile })) } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidXmlHandler.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidXmlHandler.kt similarity index 97% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidXmlHandler.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidXmlHandler.kt index c057ff00f57..46bb6615ac6 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidXmlHandler.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidXmlHandler.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic -import org.xml.sax.helpers.DefaultHandler import org.xml.sax.Attributes +import org.xml.sax.helpers.DefaultHandler import java.util.HashMap class AndroidXmlHandler(private val elementCallback: (String, String) -> Unit) : DefaultHandler() { diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/Context.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/Context.kt similarity index 98% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/Context.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/Context.kt index 18e0036bed5..adf0a8ecd50 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/Context.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/Context.kt @@ -14,11 +14,10 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic import java.util.ArrayList - open class Context(val buffer: StringBuffer = StringBuffer(), private var indentDepth: Int = 0) { open class InvalidIndent(num: Int) : RuntimeException("Indentation level < 0: $num") diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/KotlinWriter.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/KotlinWriter.kt similarity index 97% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/KotlinWriter.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/KotlinWriter.kt index 0156959f0ab..1844d28ac8f 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/KotlinWriter.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/KotlinWriter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic interface KotlinWriter { fun toStringBuffer(): StringBuffer diff --git a/plugins/android-compiler-plugin/src/AndroidExpressionCodegenExtension.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidExpressionCodegenExtension.kt similarity index 97% rename from plugins/android-compiler-plugin/src/AndroidExpressionCodegenExtension.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidExpressionCodegenExtension.kt index c28fefb52a8..90d041dbcab 100644 --- a/plugins/android-compiler-plugin/src/AndroidExpressionCodegenExtension.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidExpressionCodegenExtension.kt @@ -14,29 +14,24 @@ * limitations under the License. */ -package org.jetbrains.kotlin.android +package org.jetbrains.kotlin.android.synthetic.codegen import org.jetbrains.kotlin.codegen.ClassBuilder -import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.FunctionCodegen import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.JetTypeMapper import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.lang.resolve.android.AndroidConst +import org.jetbrains.kotlin.android.synthetic.AndroidConst import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor import org.jetbrains.kotlin.psi.JetClassOrObject -import org.jetbrains.kotlin.psi.JetFile -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor -import org.jetbrains.kotlin.resolve.scopes.receivers.ClassReceiver import org.jetbrains.kotlin.resolve.source.KotlinSourceElement -import org.jetbrains.kotlin.types.Flexibility import org.jetbrains.kotlin.types.lowerIfFlexible import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidResourceManager.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/AndroidLayoutXmlFileManager.kt similarity index 60% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidResourceManager.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/AndroidLayoutXmlFileManager.kt index f3eaa323f42..ccc10986b5c 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidResourceManager.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/AndroidLayoutXmlFileManager.kt @@ -14,21 +14,20 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic.res -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiElement +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleServiceManager import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager -import com.intellij.openapi.util.* -import com.intellij.openapi.vfs.impl.* -import com.intellij.openapi.vfs.* -import com.intellij.openapi.components.* -import com.intellij.openapi.extensions.* -import com.intellij.openapi.module.* import org.jetbrains.kotlin.psi.JetProperty +import java.util.* -public abstract class AndroidResourceManager(val project: Project) { +public abstract class AndroidLayoutXmlFileManager(val project: Project) { public abstract val androidModuleInfo: AndroidModuleInfo? @@ -42,9 +41,9 @@ public abstract class AndroidResourceManager(val project: Project) { fun VirtualFile.getAllChildren(): List { val allChildren = arrayListOf() - val currentChildren = getChildren() ?: emptyArray() + val currentChildren = children ?: emptyArray() for (child in currentChildren) { - if (child.isDirectory()) { + if (child.isDirectory) { allChildren.addAll(child.getAllChildren()) } else { @@ -57,20 +56,27 @@ public abstract class AndroidResourceManager(val project: Project) { val resDirectories = info.resDirectories.map { fileManager.findFileByUrl("file://$it") } val allChildren = resDirectories.flatMap { it?.getAllChildren() ?: listOf() } - return allChildren - .filter { it.getParent().getName().startsWith("layout") && it.getName().toLowerCase().endsWith(".xml") } - .map { psiManager.findFile(it) } - .filterNotNull() - .groupBy { it.getName().substringBeforeLast('.') } - .mapValues { it.getValue().sortBy { it.getParent()!!.getName().length() } } + val allLayoutFiles = allChildren.filter { it.parent.name.startsWith("layout") && it.name.toLowerCase().endsWith(".xml") } + val allLayoutPsiFiles = allLayoutFiles.fold(ArrayList(allLayoutFiles.size())) { list, file -> + val psiFile = psiManager.findFile(file) + if (psiFile != null && psiFile.parent != null) { + list += psiFile + } + list + } + + val layoutNameToXmls = allLayoutPsiFiles + .groupBy { it.name.substringBeforeLast('.') } + .mapValues { it.getValue().sortBy { it.parent!!.name.length() } } + + return layoutNameToXmls } companion object { - public fun getInstance(module: Module): AndroidResourceManager { - val service = ModuleServiceManager.getService(module, javaClass()) - return service ?: module.getComponent(javaClass())!! + public fun getInstance(module: Module): AndroidLayoutXmlFileManager { + val service = ModuleServiceManager.getService(module, javaClass()) + return service ?: module.getComponent(javaClass())!! } } } - diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/CliAndroidResourceManager.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliAndroidLayoutXmlFileManager.kt similarity index 89% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/CliAndroidResourceManager.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliAndroidLayoutXmlFileManager.kt index 4c807f9b3fb..867d695041d 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/CliAndroidResourceManager.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliAndroidLayoutXmlFileManager.kt @@ -14,9 +14,10 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic.res import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.android.synthetic.toMap import org.xml.sax.Attributes import org.xml.sax.helpers.DefaultHandler import java.io.File @@ -24,11 +25,11 @@ import java.io.FileInputStream import javax.xml.parsers.SAXParser import javax.xml.parsers.SAXParserFactory -public class CliAndroidResourceManager( +public class CliAndroidLayoutXmlFileManager( project: Project, private val manifestPath: String, private val resDirectories: List -) : AndroidResourceManager(project) { +) : AndroidLayoutXmlFileManager(project) { override val androidModuleInfo by lazy { AndroidModuleInfo(getApplicationPackage(manifestPath), resDirectories) @@ -60,7 +61,7 @@ public class CliAndroidResourceManager( return applicationPackage } catch (e: Exception) { - throw AndroidUIXmlProcessor.NoAndroidManifestFound() + throw SyntheticFileGenerator.NoAndroidManifestFound() } } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/CliAndroidUIXmlProcessor.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliSyntheticFileGenerator.kt similarity index 57% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/CliAndroidUIXmlProcessor.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliSyntheticFileGenerator.kt index d2eaac3df8a..b9580590167 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/CliAndroidUIXmlProcessor.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliSyntheticFileGenerator.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic.res import com.intellij.openapi.project.Project import com.intellij.openapi.util.ModificationTracker @@ -22,33 +22,41 @@ import com.intellij.psi.PsiFile import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider.Result import java.io.ByteArrayInputStream +import org.jetbrains.kotlin.android.synthetic.AndroidXmlHandler +import org.jetbrains.kotlin.android.synthetic.parseAndroidResource +import kotlin.properties.Delegates -public class CliAndroidUIXmlProcessor( +public class CliSyntheticFileGenerator( project: Project, private val manifestPath: String, - private val resDirectories: List -) : AndroidUIXmlProcessor(project) { + private val resDirectories: List, + private val supportV4: Boolean +) : SyntheticFileGenerator(project) { - override val resourceManager: CliAndroidResourceManager by lazy { - CliAndroidResourceManager(project, manifestPath, resDirectories) + override fun supportV4(): Boolean { + return supportV4 + } + + override val layoutXmlFileManager: CliAndroidLayoutXmlFileManager by Delegates.lazy { + CliAndroidLayoutXmlFileManager(project, manifestPath, resDirectories) } override val cachedSources: CachedValue> by lazy { cachedValue { - Result.create(parse(), ModificationTracker.NEVER_CHANGED) + Result.create(generateSyntheticFiles(), ModificationTracker.NEVER_CHANGED) } } - override fun parseLayout(files: List): List { + override fun extractLayoutResources(files: List): List { val resources = arrayListOf() val handler = AndroidXmlHandler { id, widgetType -> resources.add(parseAndroidResource(id, widgetType)) } try { for (file in files) { - val inputStream = ByteArrayInputStream(file.virtualFile.contentsToByteArray()) - resourceManager.saxParser.parse(inputStream, handler) + val inputStream = ByteArrayInputStream(file.getVirtualFile().contentsToByteArray()) + layoutXmlFileManager.saxParser.parse(inputStream, handler) } - return removeDuplicates(resources) + return filterDuplicates(resources) } catch (e: Throwable) { LOG.error(e) diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidUIXmlProcessor.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/SyntheticFileGenerator.kt similarity index 85% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidUIXmlProcessor.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/SyntheticFileGenerator.kt index 0a998000dd4..5f6a3e9052c 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/AndroidUIXmlProcessor.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/SyntheticFileGenerator.kt @@ -14,39 +14,38 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic.res import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager import com.intellij.psi.util.CachedValue -import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValueProvider.Result import com.intellij.psi.util.CachedValuesManager import com.intellij.testFramework.LightVirtualFile +import org.jetbrains.kotlin.android.synthetic.AndroidConst +import org.jetbrains.kotlin.android.synthetic.KotlinStringWriter +import org.jetbrains.kotlin.android.synthetic.escapeAndroidIdentifier import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.types.Flexibility public class AndroidSyntheticFile(val name: String, val contents: String) -public abstract class AndroidUIXmlProcessor(protected val project: Project) { +public abstract class SyntheticFileGenerator(protected val project: Project) { public class NoAndroidManifestFound : Exception("No android manifest file found in project root") protected val LOG: Logger = Logger.getInstance(javaClass) - public abstract val resourceManager: AndroidResourceManager + public abstract val layoutXmlFileManager: AndroidLayoutXmlFileManager protected abstract val cachedSources: CachedValue> - //MAKE CONSTANT (or abstract) - var supportV4 = false - private val cachedJetFiles: CachedValue> by lazy { cachedValue { val psiManager = PsiManager.getInstance(project) - val applicationPackage = resourceManager.androidModuleInfo?.applicationPackage + val applicationPackage = layoutXmlFileManager.androidModuleInfo?.applicationPackage val jetFiles = cachedSources.value.mapIndexed { index, syntheticFile -> val fileName = AndroidConst.SYNTHETIC_FILENAME_PREFIX + syntheticFile.name + ".kt" @@ -62,15 +61,18 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) { } } - public fun parse(generateCommonFiles: Boolean = true): List { + protected abstract fun supportV4(): Boolean + + public fun generateSyntheticFiles(generateCommonFiles: Boolean = true): List { val commonFiles = if (generateCommonFiles) { - val clearCacheFile = renderSyntheticFile("clearCache") { + val renderSyntheticFile = renderSyntheticFile("clearCache") { writePackage(AndroidConst.SYNTHETIC_PACKAGE) writeAndroidImports() writeClearCacheFunction(AndroidConst.ACTIVITY_FQNAME) writeClearCacheFunction(AndroidConst.FRAGMENT_FQNAME) - if (supportV4) writeClearCacheFunction(AndroidConst.SUPPORT_FRAGMENT_FQNAME) + if (supportV4()) writeClearCacheFunction(AndroidConst.SUPPORT_FRAGMENT_FQNAME) } + val clearCacheFile = renderSyntheticFile listOf(clearCacheFile, FLEXIBLE_TYPE_FILE, @@ -79,9 +81,9 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) { FAKE_SUPPORT_V4_WIDGET_FILE) } else listOf() - return resourceManager.getLayoutXmlFiles().flatMap { entry -> + return layoutXmlFileManager.getLayoutXmlFiles().flatMap { entry -> val files = entry.getValue() - val resources = parseLayout(files) + val resources = extractLayoutResources(files) val layoutName = files[0].name.substringBefore('.') @@ -92,15 +94,15 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) { }.filterNotNull() + commonFiles } - public fun parseToPsi(): List? = cachedJetFiles.value + public fun getSyntheticFiles(): List? = cachedJetFiles.value - protected abstract fun parseLayout(files: List): List + protected abstract fun extractLayoutResources(files: List): List private fun renderMainLayoutFile(layoutName: String, resources: List): AndroidSyntheticFile { return renderLayoutFile(layoutName + AndroidConst.LAYOUT_POSTFIX, escapeAndroidIdentifier(layoutName), resources) { val properties = it.mainProperties.toArrayList() - if (supportV4) properties.addAll(it.mainPropertiesForSupportV4) + if (supportV4()) properties.addAll(it.mainPropertiesForSupportV4) properties } } @@ -153,7 +155,7 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) { writeText("public fun $receiver.${AndroidConst.CLEAR_FUNCTION_NAME}() {}\n") } - protected fun cachedValue(result: () -> CachedValueProvider.Result): CachedValue { + protected fun cachedValue(result: () -> Result): CachedValue { return CachedValuesManager.getManager(project).createCachedValue(result, false) } @@ -161,7 +163,7 @@ public abstract class AndroidUIXmlProcessor(protected val project: Project) { return fqName.startsWith(AndroidConst.SUPPORT_V4_PACKAGE) } - protected fun removeDuplicates(resources: List): List { + protected fun filterDuplicates(resources: List): List { val resourceMap = linkedMapOf() val resourcesToExclude = hashSetOf() diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/androidResources.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/androidResources.kt similarity index 93% rename from plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/androidResources.kt rename to plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/androidResources.kt index df3a0b65877..276808f8cda 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/lang/resolve/android/androidResources.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/androidResources.kt @@ -14,7 +14,9 @@ * limitations under the License. */ -package org.jetbrains.kotlin.lang.resolve.android +package org.jetbrains.kotlin.android.synthetic.res + +import org.jetbrains.kotlin.android.synthetic.AndroidConst public data class AndroidModuleInfo(val applicationPackage: String, resDirectories: List) { val resDirectories = resDirectories.sort() @@ -40,7 +42,7 @@ public class AndroidWidget(id: String, override val className: String) : Android val MAIN_PROPERTIES_SUPPORT_V4 = listOf(AndroidConst.SUPPORT_FRAGMENT_FQNAME to "getView().findViewById(0)") - val VIEW_PROPERTIES = listOf("android.view.View" to "findViewById(0)") + val VIEW_PROPERTIES = listOf(AndroidConst.VIEW_FQNAME to "findViewById(0)") } override val mainProperties = MAIN_PROPERTIES diff --git a/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidXml2KConversionTest.kt b/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidXml2KConversionTest.kt index df666fc3cdf..eb9bbcbb36c 100644 --- a/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidXml2KConversionTest.kt +++ b/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidXml2KConversionTest.kt @@ -23,9 +23,9 @@ import org.jetbrains.kotlin.test.JetTestUtils import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.TestJdkKind import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles -import org.jetbrains.kotlin.lang.resolve.android.AndroidConst -import org.jetbrains.kotlin.lang.resolve.android.CliAndroidUIXmlProcessor -import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor +import org.jetbrains.kotlin.android.synthetic.AndroidConst +import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator +import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator import kotlin.test.* public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() { @@ -35,10 +35,10 @@ public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() { val jetCoreEnvironment = getEnvironment() val layoutPaths = getResPaths(path) - val parser = CliAndroidUIXmlProcessor(jetCoreEnvironment.project, path + "AndroidManifest.xml", layoutPaths) + val parser = CliSyntheticFileGenerator(jetCoreEnvironment.project, path + "AndroidManifest.xml", layoutPaths) parser.supportV4 = testDirectory.name.startsWith("support") - val actual = parser.parse(false).toMap { it.name } + val actual = parser.generateSyntheticFiles(false).toMap { it.name } val expectedLayoutFiles = testDirectory.listFiles { it.isFile() && it.name.endsWith(".kt") @@ -58,7 +58,7 @@ public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() { doTest(path) fail("NoAndroidManifestFound not thrown") } - catch (e: AndroidUIXmlProcessor.NoAndroidManifestFound) { + catch (e: SyntheticFileGenerator.NoAndroidManifestFound) { } } diff --git a/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/CompilerTestUtils.kt b/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/CompilerTestUtils.kt index af853702ed9..9e62dbef34d 100644 --- a/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/CompilerTestUtils.kt +++ b/plugins/android-compiler-plugin/tests/org/jetbrains/kotlin/lang/resolve/android/test/CompilerTestUtils.kt @@ -20,16 +20,16 @@ import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.project.Project import com.intellij.psi.impl.PsiTreeChangePreprocessor import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider -import org.jetbrains.kotlin.android.AndroidConfigurationKeys +import org.jetbrains.kotlin.android.synthetic.AndroidConfigurationKeys import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension -import org.jetbrains.kotlin.android.AndroidExpressionCodegenExtension +import org.jetbrains.kotlin.android.synthetic.codegen.AndroidExpressionCodegenExtension import com.intellij.testFramework.UsefulTestCase import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles -import org.jetbrains.kotlin.lang.resolve.android.CliAndroidUIXmlProcessor +import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator import java.io.File private class AndroidTestExternalDeclarationsProvider( @@ -39,9 +39,9 @@ private class AndroidTestExternalDeclarationsProvider( val supportV4: Boolean ) : ExternalDeclarationsProvider { override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection { - val parser = CliAndroidUIXmlProcessor(project, manifestPath, resPaths) + val parser = CliSyntheticFileGenerator(project, manifestPath, resPaths) parser.supportV4 = supportV4 - return parser.parseToPsi() ?: listOf() + return parser.getSyntheticFiles() ?: listOf() } } diff --git a/plugins/android-idea-plugin/src/META-INF/plugin.xml b/plugins/android-idea-plugin/src/META-INF/plugin.xml index 877dc91afbf..921c1a6b0cc 100644 --- a/plugins/android-idea-plugin/src/META-INF/plugin.xml +++ b/plugins/android-idea-plugin/src/META-INF/plugin.xml @@ -12,22 +12,22 @@ org.jetbrains.android - - + + - - + + - - - - + + + + diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidFindMemberUsagesHandler.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidFindMemberUsagesHandler.kt similarity index 84% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidFindMemberUsagesHandler.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidFindMemberUsagesHandler.kt index a0ed2df9800..dde30bf58da 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidFindMemberUsagesHandler.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidFindMemberUsagesHandler.kt @@ -14,28 +14,27 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea import com.intellij.find.findUsages.FindUsagesHandler +import com.intellij.find.findUsages.FindUsagesOptions +import com.intellij.find.findUsages.JavaVariableFindUsagesOptions +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.module.ModuleServiceManager import com.intellij.psi.PsiElement +import com.intellij.psi.xml.XmlAttribute import com.intellij.usageView.UsageInfo import com.intellij.util.Processor -import com.intellij.find.findUsages.FindUsagesOptions -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.components.ServiceManager -import com.intellij.psi.xml.XmlAttribute import org.jetbrains.android.util.AndroidResourceUtil -import java.util.ArrayList -import com.intellij.find.findUsages.JavaVariableFindUsagesOptions -import com.intellij.openapi.module.ModuleServiceManager +import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement +import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo import org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator import org.jetbrains.kotlin.psi.JetNamedDeclaration import org.jetbrains.kotlin.psi.JetProperty -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.lang.resolve.android.isAndroidSyntheticElement -import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor +import java.util.ArrayList class AndroidFindUsageHandlerDecorator : KotlinFindUsagesHandlerDecorator { override fun decorateHandler(element: PsiElement, forHighlightUsages: Boolean, delegate: FindUsagesHandler): FindUsagesHandler { @@ -56,9 +55,9 @@ class AndroidFindMemberUsagesHandler( val property = declaration as JetProperty val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements() - val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass()) + val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass()) - val psiElements = parser?.resourceManager?.propertyToXmlAttributes(property) + val psiElements = parser?.layoutXmlFileManager?.propertyToXmlAttributes(property) val valueElements = psiElements?.map { (it as? XmlAttribute)?.getValueElement() as? PsiElement }?.filterNotNull() if (valueElements != null && valueElements.isNotEmpty()) return valueElements.toTypedArray() @@ -74,9 +73,9 @@ class AndroidFindMemberUsagesHandler( val property = declaration as JetProperty val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements() - val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass()) + val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass()) - val psiElements = parser?.resourceManager?.propertyToXmlAttributes(property) ?: listOf() + val psiElements = parser?.layoutXmlFileManager?.propertyToXmlAttributes(property) ?: listOf() val res = ArrayList() for (psiElement in psiElements) { @@ -97,7 +96,7 @@ class AndroidFindMemberUsagesHandler( override fun processElementUsages(element: PsiElement, processor: Processor, options: FindUsagesOptions): Boolean { assert(isAndroidSyntheticElement(declaration)) - val findUsagesOptions = JavaVariableFindUsagesOptions(runReadAction { element.getProject() }) + val findUsagesOptions = JavaVariableFindUsagesOptions(runReadAction { element.project }) findUsagesOptions.isSearchForTextOccurrences = false findUsagesOptions.isSkipImportStatements = true findUsagesOptions.isUsages = true @@ -105,4 +104,9 @@ class AndroidFindMemberUsagesHandler( findUsagesOptions.isWriteAccess = true return super.processElementUsages(element, processor, findUsagesOptions) } + + // Android extensions plugin has it's own runtime -> different function classes + private fun runReadAction(action: () -> T): T { + return ApplicationManager.getApplication().runReadAction(action) + } } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidGotoDeclarationHandler.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidGotoDeclarationHandler.kt similarity index 89% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidGotoDeclarationHandler.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidGotoDeclarationHandler.kt index b4ddb02921a..70a52a6853c 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidGotoDeclarationHandler.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidGotoDeclarationHandler.kt @@ -14,21 +14,21 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea -import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler -import com.intellij.psi.PsiElement -import com.intellij.openapi.editor.Editor -import com.intellij.psi.impl.source.tree.LeafPsiElement -import org.jetbrains.kotlin.psi.JetSimpleNameExpression -import org.jetbrains.kotlin.psi.JetProperty -import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo -import com.intellij.psi.xml.XmlAttribute import com.intellij.openapi.actionSystem.DataContext -import org.jetbrains.kotlin.idea.references.JetSimpleNameReference +import com.intellij.openapi.editor.Editor import com.intellij.openapi.module.ModuleServiceManager -import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor +import com.intellij.psi.PsiElement +import com.intellij.psi.impl.source.tree.LeafPsiElement +import com.intellij.psi.xml.XmlAttribute +import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator +import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo +import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo +import org.jetbrains.kotlin.idea.references.JetSimpleNameReference +import org.jetbrains.kotlin.psi.JetProperty +import org.jetbrains.kotlin.psi.JetSimpleNameExpression public class AndroidGotoDeclarationHandler : GotoDeclarationHandler { @@ -40,8 +40,8 @@ public class AndroidGotoDeclarationHandler : GotoDeclarationHandler { val moduleInfo = sourceElement.getModuleInfo() if (moduleInfo !is ModuleSourceInfo) return null - val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass())!! - val psiElements = parser.resourceManager.propertyToXmlAttributes(property) + val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass())!! + val psiElements = parser.layoutXmlFileManager.propertyToXmlAttributes(property) val valueElements = psiElements.map { (it as? XmlAttribute)?.getValueElement() as? PsiElement }.filterNotNull() if (valueElements.isNotEmpty()) return valueElements.toTypedArray() } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidPsiTreeChangePreprocessor.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidPsiTreeChangePreprocessor.kt similarity index 90% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidPsiTreeChangePreprocessor.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidPsiTreeChangePreprocessor.kt index 59d1f21c1d6..b4d524062ff 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidPsiTreeChangePreprocessor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidPsiTreeChangePreprocessor.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea import com.intellij.ide.highlighter.XmlFileType import com.intellij.openapi.roots.ProjectRootManager @@ -25,7 +25,7 @@ import com.intellij.psi.PsiFile import com.intellij.psi.impl.PsiTreeChangeEventImpl import com.intellij.psi.impl.PsiTreeChangePreprocessor import com.intellij.psi.xml.XmlFile -import org.jetbrains.kotlin.lang.resolve.android.AndroidResourceManager +import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, SimpleModificationTracker() { @@ -47,7 +47,7 @@ public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, Simpl val projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex() val module = projectFileIndex.getModuleForFile(file.getVirtualFile()) if (module != null) { - val resourceManager = AndroidResourceManager.getInstance(module) + val resourceManager = AndroidLayoutXmlFileManager.getInstance(module) val resDirectories = resourceManager.getModuleResDirectories() val baseDirectory = file.getParent()?.getParent()?.getVirtualFile() @@ -60,7 +60,7 @@ public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, Simpl } } - private fun AndroidResourceManager.getModuleResDirectories(): List { + private fun AndroidLayoutXmlFileManager.getModuleResDirectories(): List { val info = androidModuleInfo ?: return listOf() val fileManager = VirtualFileManager.getInstance() diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidRenameProcessor.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidRenameProcessor.kt similarity index 87% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidRenameProcessor.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidRenameProcessor.kt index 7bdb59132b8..81143ccf419 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidRenameProcessor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidRenameProcessor.kt @@ -14,34 +14,31 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea -import org.jetbrains.kotlin.asJava.namedUnwrappedElement -import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo -import org.jetbrains.kotlin.psi.moduleInfo -import com.intellij.refactoring.rename.RenamePsiElementProcessor -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.psi.JetProperty -import com.intellij.psi.xml.XmlAttributeValue -import com.intellij.psi.PsiField -import com.intellij.psi.PsiClass -import com.intellij.openapi.module.Module -import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo -import org.jetbrains.kotlin.psi.JetFile -import com.intellij.psi.search.SearchScope -import com.intellij.psi.impl.light.LightElement -import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor -import com.intellij.psi.xml.XmlAttribute -import org.jetbrains.kotlin.lang.resolve.android -import org.jetbrains.kotlin.lang.resolve.android.AndroidConst -import com.intellij.openapi.module.ModuleServiceManager -import org.jetbrains.android.util.AndroidResourceUtil -import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper -import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.components.ServiceManager -import org.jetbrains.kotlin.lang.resolve.android.isAndroidSyntheticElement -import org.jetbrains.kotlin.lang.resolve.android.nameToIdDeclaration -import org.jetbrains.kotlin.lang.resolve.android.idToName +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleServiceManager +import com.intellij.openapi.module.ModuleUtilCore +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiField +import com.intellij.psi.impl.light.LightElement +import com.intellij.psi.search.SearchScope +import com.intellij.psi.xml.XmlAttribute +import com.intellij.psi.xml.XmlAttributeValue +import com.intellij.refactoring.rename.RenamePsiElementProcessor +import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper +import org.jetbrains.android.util.AndroidResourceUtil +import org.jetbrains.kotlin.android.synthetic.AndroidConst +import org.jetbrains.kotlin.android.synthetic.idToName +import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement +import org.jetbrains.kotlin.android.synthetic.nameToIdDeclaration +import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator +import org.jetbrains.kotlin.asJava.namedUnwrappedElement +import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo +import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo +import org.jetbrains.kotlin.psi.JetProperty public class AndroidRenameProcessor : RenamePsiElementProcessor() { @@ -93,8 +90,8 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() { ) { val module = jetProperty.getModule() ?: return - val processor = ModuleServiceManager.getService(module, javaClass())!! - val resourceManager = processor.resourceManager + val processor = ModuleServiceManager.getService(module, javaClass())!! + val resourceManager = processor.layoutXmlFileManager val psiElements = resourceManager.propertyToXmlAttributes(jetProperty).map { it as? XmlAttribute }.filterNotNull() @@ -120,7 +117,7 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() { val module = attribute.getModule() ?: ModuleUtilCore.findModuleForFile( attribute.getContainingFile().getVirtualFile(), attribute.getProject()) ?: return - val processor = ModuleServiceManager.getService(module, javaClass())!! + val processor = ModuleServiceManager.getService(module, javaClass())!! if (element == null) return val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()) val newPropName = idToName(newName) @@ -133,9 +130,9 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() { allRenames: MutableMap, newPropName: String, oldPropName: String, - processor: AndroidUIXmlProcessor + processor: SyntheticFileGenerator ) { - val props = processor.parseToPsi()?.flatMap { it.findChildrenByClass(javaClass()).toList() } + val props = processor.getSyntheticFiles()?.flatMap { it.findChildrenByClass(javaClass()).toList() } val matchedProps = props?.filter { it.getName() == oldPropName } ?: listOf() for (prop in matchedProps) { allRenames[prop] = newPropName @@ -148,7 +145,7 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() { allRenames: MutableMap ) { val oldName = field.getName()!! - val processor = ServiceManager.getService(field.getProject(), javaClass()) + val processor = ServiceManager.getService(field.getProject(), javaClass()) renameSyntheticProperties(allRenames, newName, oldName, processor) } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidSimpleNameReferenceExtension.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt similarity index 82% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidSimpleNameReferenceExtension.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt index 2e51648ce12..399be1568da 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidSimpleNameReferenceExtension.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt @@ -14,24 +14,24 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea -import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension -import org.jetbrains.kotlin.idea.references.JetSimpleNameReference import com.intellij.psi.PsiElement import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper +import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement +import org.jetbrains.kotlin.idea.references.JetSimpleNameReference +import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension import org.jetbrains.kotlin.psi.JetProperty import org.jetbrains.kotlin.psi.JetPsiFactory -import org.jetbrains.kotlin.lang.resolve.android.isAndroidSyntheticElement public class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension { override fun isReferenceTo(reference: JetSimpleNameReference, element: PsiElement): Boolean? { - val resolvedElement = reference.resolve() ?: return null + val resolvedElement = reference.resolve() as? JetProperty ?: return null if (isAndroidSyntheticElement(resolvedElement)) { if (element is ValueResourceElementWrapper) { - val resource = element.getValue() - return (resolvedElement as JetProperty).getName() == resource.substring(resource.indexOf('/') + 1) + val resource = element.value + return resolvedElement.name == resource.substring(resource.indexOf('/') + 1) } } return null diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidXmlVisitor.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidXmlVisitor.kt similarity index 81% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidXmlVisitor.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidXmlVisitor.kt index 29680d0d5ea..c99994d97e6 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/AndroidXmlVisitor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidXmlVisitor.kt @@ -14,15 +14,16 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea -import com.intellij.psi.xml.XmlAttribute -import com.intellij.psi.XmlElementVisitor import com.intellij.psi.PsiElement +import com.intellij.psi.XmlElementVisitor +import com.intellij.psi.xml.XmlAttribute import com.intellij.psi.xml.XmlElement import com.intellij.psi.xml.XmlTag -import org.jetbrains.kotlin.lang.resolve.android -import org.jetbrains.kotlin.lang.resolve.android.* +import org.jetbrains.kotlin.android.synthetic.AndroidConst +import org.jetbrains.kotlin.android.synthetic.idToName +import org.jetbrains.kotlin.android.synthetic.isWidgetTypeIgnored class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> Unit) : XmlElementVisitor() { @@ -35,7 +36,7 @@ class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> U } override fun visitXmlTag(tag: XmlTag?) { - val localName = tag?.getLocalName() ?: "" + val localName = tag?.localName ?: "" if (isWidgetTypeIgnored(localName)) { tag?.acceptChildren(this) return @@ -43,9 +44,9 @@ class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> U val idAttribute = tag?.getAttribute(AndroidConst.ID_ATTRIBUTE) if (idAttribute != null) { - val idAttributeValue = idAttribute.getValue() + val idAttributeValue = idAttribute.value if (idAttributeValue != null) { - val xmlType = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.getValue() ?: localName + val xmlType = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.value ?: localName val name = idToName(idAttributeValue) if (name != null) elementCallback(name, xmlType, idAttribute) } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidExternalDeclarationsProvider.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/IDEAndroidExternalDeclarationsProvider.kt similarity index 86% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidExternalDeclarationsProvider.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/IDEAndroidExternalDeclarationsProvider.kt index b9db07a49fb..01e67011ef5 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidExternalDeclarationsProvider.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/IDEAndroidExternalDeclarationsProvider.kt @@ -14,15 +14,15 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea -import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.psi.JetFile -import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo import com.intellij.openapi.module.ModuleServiceManager -import org.jetbrains.kotlin.lang.resolve.android.AndroidUIXmlProcessor +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator +import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider +import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo +import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.moduleInfo public class IDEAndroidExternalDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider { @@ -30,8 +30,8 @@ public class IDEAndroidExternalDeclarationsProvider(private val project: Project if (moduleInfo !is ModuleSourceInfo) return listOf() val module = moduleInfo.module - val parser = ModuleServiceManager.getService(module, javaClass())!! - val syntheticFiles = parser.parseToPsi() + val parser = ModuleServiceManager.getService(module, javaClass())!! + val syntheticFiles = parser.getSyntheticFiles() syntheticFiles?.forEach { it.moduleInfo = moduleInfo } return syntheticFiles ?: listOf() diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/TestConst.java b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/TestConst.java similarity index 93% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/TestConst.java rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/TestConst.java index 844686b750d..fb4591a534c 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/TestConst.java +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/TestConst.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android; +package org.jetbrains.kotlin.android.synthetic.idea; import com.intellij.openapi.util.Key; diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/XmlAttributeValueWrapper.java b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/XmlAttributeValueWrapper.java similarity index 99% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/XmlAttributeValueWrapper.java rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/XmlAttributeValueWrapper.java index a271aceecef..29283be78ed 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/XmlAttributeValueWrapper.java +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/XmlAttributeValueWrapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android; +package org.jetbrains.kotlin.android.synthetic.idea; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidResourceManager.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt similarity index 75% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidResourceManager.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt index 537ce8e26b5..9cdfca19f0f 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidResourceManager.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt @@ -14,21 +14,20 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea.res import com.intellij.openapi.module.Module import com.intellij.psi.PsiElement import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.kotlin.lang.resolve.android.AndroidConst -import kotlin.properties.Delegates -import org.jetbrains.kotlin.plugin.android.AndroidXmlVisitor -import org.jetbrains.kotlin.lang.resolve.android.AndroidResourceManager -import org.jetbrains.kotlin.lang.resolve.android.AndroidModuleInfo +import org.jetbrains.kotlin.android.synthetic.AndroidConst +import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor +import org.jetbrains.kotlin.android.synthetic.res.AndroidModuleInfo +import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager import org.jetbrains.kotlin.psi.JetProperty -public class IDEAndroidResourceManager(val module: Module) : AndroidResourceManager(module.getProject()) { +public class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileManager(module.getProject()) { - override val androidModuleInfo: AndroidModuleInfo? by Delegates.lazy { module.androidFacet?.toAndroidModuleInfo() } + override val androidModuleInfo: AndroidModuleInfo? by lazy { module.androidFacet?.toAndroidModuleInfo() } override fun propertyToXmlAttributes(property: JetProperty): List { val fqPath = property.getFqName()?.pathSegments() ?: return listOf() @@ -53,7 +52,7 @@ public class IDEAndroidResourceManager(val module: Module) : AndroidResourceMana get() = AndroidFacet.getInstance(this) private fun AndroidFacet.toAndroidModuleInfo(): AndroidModuleInfo? { - val applicationPackage = getManifest()?.getPackage()?.toString() + val applicationPackage = manifest?.getPackage()?.toString() val mainResDirectories = getAllResourceDirectories().map { it.getPath() } return if (applicationPackage != null) { diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidUIXmlProcessor.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt similarity index 52% rename from plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidUIXmlProcessor.kt rename to plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt index 49432fe9456..a5b940e9ec0 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/plugin/android/IDEAndroidUIXmlProcessor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt @@ -14,21 +14,25 @@ * limitations under the License. */ -package org.jetbrains.kotlin.plugin.android +package org.jetbrains.kotlin.android.synthetic.idea.res -import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.module.Module import com.intellij.psi.JavaPsiFacade -import org.jetbrains.kotlin.plugin.android.IDEAndroidResourceManager import com.intellij.psi.PsiFile -import org.jetbrains.kotlin.plugin.android.AndroidXmlVisitor -import com.intellij.psi.impl.* -import kotlin.properties.* -import org.jetbrains.kotlin.lang.resolve.android.* +import com.intellij.psi.impl.PsiTreeChangePreprocessor import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider.Result +import org.jetbrains.kotlin.android.synthetic.AndroidConst +import org.jetbrains.kotlin.android.synthetic.idea.AndroidPsiTreeChangePreprocessor +import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor +import org.jetbrains.kotlin.android.synthetic.parseAndroidResource +import org.jetbrains.kotlin.android.synthetic.res.AndroidResource +import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFile +import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator -class IDEAndroidUIXmlProcessor(val module: Module) : AndroidUIXmlProcessor(module.getProject()) { +class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(module.project) { + + private val supportV4: Boolean init { val scope = module.getModuleWithDependenciesAndLibrariesScope(false) @@ -36,26 +40,28 @@ class IDEAndroidUIXmlProcessor(val module: Module) : AndroidUIXmlProcessor(modul .findClasses(AndroidConst.SUPPORT_FRAGMENT_FQNAME, scope).isNotEmpty() } - override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(module) + override fun supportV4() = supportV4 - private val psiTreeChangePreprocessor by Delegates.lazy { - module.getProject().getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor } + override val layoutXmlFileManager: IDEAndroidLayoutXmlFileManager = IDEAndroidLayoutXmlFileManager(module) + + private val psiTreeChangePreprocessor by lazy { + module.project.getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor } } - override val cachedSources: CachedValue> by Delegates.lazy { + override val cachedSources: CachedValue> by lazy { cachedValue { - Result.create(parse(), psiTreeChangePreprocessor) + Result.create(generateSyntheticFiles(), psiTreeChangePreprocessor) } } - override fun parseLayout(files: List): List { + override fun extractLayoutResources(files: List): List { val widgets = arrayListOf() val visitor = AndroidXmlVisitor { id, widgetType, attribute -> widgets.add(parseAndroidResource(id, widgetType)) } files.forEach { it.accept(visitor) } - return removeDuplicates(widgets) + return filterDuplicates(widgets) } } \ No newline at end of file diff --git a/plugins/android-idea-plugin/tests/org/jetbrains/kotlin/android/AbstractParserResultEqualityTest.kt b/plugins/android-idea-plugin/tests/org/jetbrains/kotlin/android/AbstractParserResultEqualityTest.kt index d2acdca5940..94edf82ce45 100644 --- a/plugins/android-idea-plugin/tests/org/jetbrains/kotlin/android/AbstractParserResultEqualityTest.kt +++ b/plugins/android-idea-plugin/tests/org/jetbrains/kotlin/android/AbstractParserResultEqualityTest.kt @@ -16,16 +16,10 @@ package org.jetbrains.kotlin.android -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.plugin.android.TestConst -import org.jetbrains.kotlin.lang.resolve.android.CliAndroidUIXmlProcessor +import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator import com.intellij.openapi.module.ModuleManager -import org.jetbrains.kotlin.plugin.android.IDEAndroidUIXmlProcessor -import org.jetbrains.kotlin.test.ConfigurationKind -import org.jetbrains.kotlin.test.TestJdkKind -import org.jetbrains.kotlin.test.JetTestUtils -import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles -import java.io.File +import org.jetbrains.kotlin.android.synthetic.idea.TestConst +import org.jetbrains.kotlin.android.synthetic.idea.res.IDESyntheticFileGenerator import kotlin.test.assertEquals public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase() { @@ -37,11 +31,11 @@ public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase() "$path${it.name}/" } - val cliParser = CliAndroidUIXmlProcessor(project, path + "../AndroidManifest.xml", resDirs) - val ideParser = IDEAndroidUIXmlProcessor(ModuleManager.getInstance(project).getModules()[0]) + val cliParser = CliSyntheticFileGenerator(project, path + "../AndroidManifest.xml", resDirs, false) + val ideParser = IDESyntheticFileGenerator(ModuleManager.getInstance(project).getModules()[0]) - val cliResult = cliParser.parseToPsi()!!.joinToString("\n\n") - val ideResult = ideParser.parseToPsi()!!.joinToString("\n\n") + val cliResult = cliParser.getSyntheticFiles()!!.joinToString("\n\n") + val ideResult = ideParser.getSyntheticFiles()!!.joinToString("\n\n") assertEquals(cliResult, ideResult) }