diff --git a/plugins/android-compiler-plugin/src/AndroidComponentRegistrar.kt b/plugins/android-compiler-plugin/src/AndroidComponentRegistrar.kt index e53ac0177d6..baaf4e02d84 100644 --- a/plugins/android-compiler-plugin/src/AndroidComponentRegistrar.kt +++ b/plugins/android-compiler-plugin/src/AndroidComponentRegistrar.kt @@ -83,7 +83,7 @@ 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 emptyOrSingletonList(parser?.parseToPsi(project)) + return emptyOrSingletonList(parser.parseToPsi()) } } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidConst.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidConst.kt new file mode 100644 index 00000000000..be2de168304 --- /dev/null +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidConst.kt @@ -0,0 +1,48 @@ +/* + * 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.lang.resolve.android + +import com.intellij.openapi.util.Key + +public object AndroidConst { + val ANDROID_USER_PACKAGE: Key = Key.create("ANDROID_USER_PACKAGE") + val SYNTHETIC_FILENAME: String = "ANDROIDXML.kt" + + val ANDROID_NAMESPACE: String = "android" + val ID_ATTRIBUTE_NO_NAMESPACE: String = "id" + val ID_ATTRIBUTE: String = "$ANDROID_NAMESPACE:$ID_ATTRIBUTE_NO_NAMESPACE" + val CLASS_ATTRIBUTE_NO_NAMESPACE: String = "class" + + val ID_DECLARATION_PREFIX = "@+id/" + val ID_USAGE_PREFIX = "@id/" +} + +class WrongIdFormat(id: String) : Exception("Id \"$id\" has wrong format") + +public fun nameToIdDeclaration(name: String): String = AndroidConst.ID_DECLARATION_PREFIX + name + +public fun idToName(id: String): String { + return if (isResourceIdDeclaration(id)) id.replace(AndroidConst.ID_DECLARATION_PREFIX, "") + else if (isResourceIdUsage(id)) id.replace(AndroidConst.ID_USAGE_PREFIX, "") + else throw WrongIdFormat(id) +} + +public fun isResourceIdDeclaration(str: String?): Boolean = str?.startsWith(AndroidConst.ID_DECLARATION_PREFIX) ?: false + +public fun isResourceIdUsage(str: String?): Boolean = str?.startsWith(AndroidConst.ID_USAGE_PREFIX) ?: false + +public fun isResourceDeclarationOrUsage(id: String?): Boolean = isResourceIdDeclaration(id) || isResourceIdUsage(id) diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidResourceManager.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidResourceManager.kt index f08cdd77ab1..1108218e247 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidResourceManager.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidResourceManager.kt @@ -19,32 +19,47 @@ package org.jetbrains.jet.lang.resolve.android import com.intellij.psi.PsiFile import com.intellij.psi.PsiElement import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.psi.PsiManager +import com.intellij.openapi.vfs.VirtualFile -public abstract class AndroidResourceManager(protected val project: Project, protected val searchPath: String?) { - private val idDeclarationPrefix = "@+id/" - private val idUsagePrefix = "@id/" - public val androidNamespace: String = "android" - public val idAttributeNoNamespace: String = "id" - public val idAttribute: String = androidNamespace + ":" + idAttributeNoNamespace - public val classAttributeNoNamespace: String = "class" - public val classAttribute: String = androidNamespace + ":" + classAttributeNoNamespace +public abstract class AndroidResourceManager(val project: Project) { - abstract fun getLayoutXmlFiles(): Collection - public abstract fun idToXmlAttribute(id: String): PsiElement? - public fun nameToIdDeclaration(name: String): String = idDeclarationPrefix + name - public fun nameToIdUsage(name: String): String = idUsagePrefix + name - public fun idToName(id: String?): String { - return if (isResourceIdDeclaration(id)) id!!.replace(idDeclarationPrefix, "") - else if (isResourceIdUsage(id)) id!!.replace(idUsagePrefix, "") - else throw WrongIdFormat(id) + public abstract val androidModuleInfo: AndroidModuleInfo? + + public open fun idToXmlAttribute(id: String): PsiElement? = null + + open fun getLayoutXmlFiles(): List { + val info = androidModuleInfo + if (info == null) return listOf() + + val psiManager = PsiManager.getInstance(project) + val fileManager = VirtualFileManager.getInstance() + + fun VirtualFile.getAllChildren(): List { + val allChildren = arrayListOf() + val currentChildren = getChildren() ?: array() + for (child in currentChildren) { + if (child.isDirectory()) { + allChildren.addAll(child.getAllChildren()) + } + else { + allChildren.add(child) + } + } + return allChildren + } + + val resDirectory = fileManager.findFileByUrl("file://" + info.mainResDirectory) + val allChildren = resDirectory?.getAllChildren() ?: listOf() + + return allChildren + .filter { it.getParent().getName().startsWith("layout") && it.getName().toLowerCase().endsWith(".xml") } + .map { psiManager.findFile(it) } + .filterNotNull() + .sortBy { it.getName() } } - public fun isResourceIdDeclaration(str: String?): Boolean = str?.startsWith(idDeclarationPrefix) ?: false - public fun isResourceIdUsage(str: String?): Boolean = str?.startsWith(idUsagePrefix) ?: false - public fun isResourceDeclarationOrUsage(id: String?): Boolean = isResourceIdDeclaration(id) || isResourceIdUsage(id) - abstract fun readManifest(): AndroidManifest - - inner class NoUIXMLsFound : Exception("No android UI xmls found in $searchPath") - inner class WrongIdFormat(id: String?) : Exception("Id \"$id\" has wrong format") + inner class NoLayoutXmlFound : Exception("No android UI xmls found in " + androidModuleInfo?.mainResDirectory) } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidResourceManagerBase.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidResourceManagerBase.kt deleted file mode 100644 index fa11e4604da..00000000000 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidResourceManagerBase.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.lang.resolve.android - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.psi.PsiManager -import java.util.ArrayList -import com.intellij.openapi.vfs.VirtualFile - -abstract class AndroidResourceManagerBase(project: Project, searchPath: String?) : AndroidResourceManager(project, searchPath) { - override fun getLayoutXmlFiles(): Collection { - val fileManager = VirtualFileManager.getInstance() - val watchDir = fileManager.findFileByUrl("file://" + searchPath) - val psiManager = PsiManager.getInstance(project) - val files = watchDir?.getChildren()?.toArrayList()?.map { psiManager.findFile(it) }?.mapNotNull { it } ?: listOf() - return files.sortBy({it.getName()}) - } - - protected fun virtualFileToPsi(vf: VirtualFile): PsiFile? { - val psiManager = PsiManager.getInstance(project) - return psiManager.findFile(vf) - - } - - override fun idToXmlAttribute(id: String): PsiElement? { - return null - } -} diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidUIXmlProcessor.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidUIXmlProcessor.kt index c3c8760d567..96882ec475e 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidUIXmlProcessor.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidUIXmlProcessor.kt @@ -46,124 +46,89 @@ import com.intellij.psi.impl.PsiModificationTrackerImpl import java.util.Queue import com.intellij.psi.PsiFile import com.intellij.openapi.diagnostic.Logger -import org.jetbrains.jet.lang.resolve.android.AndroidConst.* -import org.jetbrains.jet.analyzer.ModuleInfo import com.intellij.openapi.module.Module +import com.intellij.psi.util.CachedValue +import com.intellij.psi.util.CachedValueProvider +import com.intellij.psi.util.CachedValuesManager +import com.intellij.psi.util.CachedValueProvider.Result +import java.util.concurrent.atomic.AtomicInteger +import com.intellij.openapi.roots.ProjectRootModificationTracker +import com.intellij.openapi.util.ModificationTracker public abstract class AndroidUIXmlProcessor(protected val project: Project) { public class NoAndroidManifestFound : Exception("No android manifest file found in project root") - private enum class CacheAction { HIT; MISS } + private val androidImports = listOf( + "android.app.Activity", + "android.view.View", + "android.widget.*") - private val androidImports = arrayListOf("android.app.Activity", - "android.view.View", - "android.widget.*") + //TODO + private val cachedSources = cachedValue { + Result.create(parse(), ProjectRootModificationTracker.getInstance(project)) + } - protected abstract val searchPath: String? - protected abstract val androidAppPackage: String + private val cachedJetFiles = cachedValue { + val psiManager = PsiManager.getInstance(project) + val applicationPackage = resourceManager.androidModuleInfo?.applicationPackage - private val fileCache = HashMap() - var lastCachedPsi: JetFile? = null - private set - protected val fileModificationTime: HashMap = HashMap() + val jetFiles = cachedSources.getValue().mapIndexed { (index, text) -> + val virtualFile = LightVirtualFile(AndroidConst.SYNTHETIC_FILENAME + index + ".kt", text) + val jetFile = psiManager.findFile(virtualFile) as JetFile + if (applicationPackage != null) { + jetFile.putUserData(AndroidConst.ANDROID_USER_PACKAGE, applicationPackage) + } + jetFile + } - protected val filesToProcess: Queue = ConcurrentLinkedQueue() + Result.create(jetFiles, cachedSources) + } public abstract val resourceManager: AndroidResourceManager - protected val LOG: Logger = Logger.getInstance(this.javaClass) + protected val LOG: Logger = Logger.getInstance(javaClass) - public fun parseToString(): String? { - val cacheState = doParse() - if (cacheState == null) return null - return renderString() + public fun parse(): List { + return resourceManager.getLayoutXmlFiles().map { file -> + val widgets = parseSingleFile(file) + if (widgets.isNotEmpty()) { + val layoutPackage = file.genSyntheticPackageName() + val stringWriter = KotlinStringWriter() + + stringWriter.writePackage(layoutPackage) + stringWriter.writeAndroidImports() + widgets.forEach { stringWriter.writeSyntheticActivityProperty(it) } + + val contents = stringWriter.toStringBuffer().toString() + contents + } else null + }.filterNotNull() } + public fun parseToPsi(): List? = cachedJetFiles.getValue() - public fun parseToPsi(project: Project): JetFile? { - val cacheState = doParse() - if (cacheState == null) return null - return if (cacheState == CacheAction.MISS || lastCachedPsi == null) { - try { - val vf = LightVirtualFile(SYNTHETIC_FILENAME, renderString()) - val psiFile = PsiManager.getInstance(project).findFile(vf) as JetFile - psiFile.putUserData(ANDROID_USER_PACKAGE, androidAppPackage) - lastCachedPsi = psiFile - psiFile - } - catch (e: Exception) { - invalidateCaches() - null - } - } - else lastCachedPsi + protected abstract fun parseSingleFile(file: PsiFile): Collection + + private fun KotlinStringWriter.writeAndroidImports() { + androidImports.forEach { writeImport(it) } + writeEmptyLine() } - private fun writeImports(kw: KotlinStringWriter): KotlinWriter { - kw.writePackage(androidAppPackage) - for (elem in androidImports) - kw.writeImport(elem) - kw.writeEmptyLine() - return kw + private fun PsiFile.genSyntheticPackageName(): String { + return AndroidConst.SYNTHETIC_PACKAGE + getName().substringBefore('.') } - private fun parseSingleFileWithCache(file: PsiFile): Pair { - val lastRecorded = fileModificationTime[file] ?: -1 - if (file.getModificationStamp() > lastRecorded) - return Pair(parseSingleFile(file), CacheAction.MISS) - else - return Pair(fileCache[file]!!, CacheAction.HIT) + private fun KotlinStringWriter.writeSyntheticActivityProperty(widget: AndroidWidget) { + val body = arrayListOf("return findViewById(0) as ${widget.className}") + writeImmutableExtensionProperty(receiver = "Activity", + name = widget.id, + retType = widget.className, + getterBody = body) } - private fun parseSingleFile(file: PsiFile): String { - val res = parseSingleFileImpl(file) - fileModificationTime[file] = file.getModificationStamp() - fileCache[file] = res - return res + private fun cachedValue(result: () -> CachedValueProvider.Result): CachedValue { + return CachedValuesManager.getManager(project).createCachedValue(result, false) } - protected abstract fun parseSingleFileImpl(file: PsiFile): String - - private fun doParse(): CacheAction? { - if (searchPath == null || searchPath == "") return null - populateQueue() - var overallCacheMiss = false - var file = filesToProcess.poll() - while (file != null) { - val res = parseSingleFileWithCache(file!!) - overallCacheMiss = overallCacheMiss or (res.second == CacheAction.MISS) - file = filesToProcess.poll() - } - return if (overallCacheMiss) CacheAction.MISS else CacheAction.HIT - } - - private fun renderString(): String { - val buffer = writeImports(KotlinStringWriter()).output() - for (buf in fileCache.entrySet().sortBy({it.key.getName()})) - buffer.append(buf.value) - return buffer.toString() - } - - private fun invalidateCaches() { - fileCache.clear() - fileModificationTime.clear() - lastCachedPsi = null - } - - protected fun populateQueue() { - filesToProcess.addAll(resourceManager.getLayoutXmlFiles()) - } - - - protected fun produceKotlinProperties(kw: KotlinStringWriter, ids: Collection): StringBuffer { - for (id in ids) { - val body = arrayListOf("return findViewById(0) as ${id.className}") - kw.writeImmutableExtensionProperty(receiver = "Activity", - name = id.id, - retType = id.className, - getterBody = body) - } - return kw.output() - } } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidUtil.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidUtil.kt index 08988a5f431..8414452c2cd 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidUtil.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidUtil.kt @@ -26,25 +26,7 @@ import com.intellij.psi.PsiClass import org.jetbrains.jet.utils.emptyOrSingletonList import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.util.Computable - -trait AndroidResource - -class AndroidID(val rawID: String) : AndroidResource { - - override fun equals(other: Any?): Boolean { - return other is AndroidID && this.rawID == other.rawID - } - override fun hashCode(): Int { - return rawID.hashCode() - } - override fun toString(): String { - return rawID - } -} - -public class AndroidWidget(val id: String, val className: String) : AndroidResource - -public class AndroidManifest(public val _package: String) : AndroidResource +import com.intellij.openapi.module.ModuleServiceManager fun isAndroidSyntheticFile(f: PsiFile?): Boolean { return f?.getUserData(org.jetbrains.jet.lang.resolve.android.AndroidConst.ANDROID_USER_PACKAGE) != null @@ -55,15 +37,3 @@ public fun isAndroidSyntheticElement(element: PsiElement?): Boolean { element?.getContainingFile() })) } - -public fun isRClassField(element: PsiElement): Boolean { - return if (element is PsiField) { - val outerClass = element.getParent()?.getParent() - if (outerClass !is PsiClass) return false - val processor = ServiceManager.getService(element.getProject(), javaClass()) - val packageName = processor?.resourceManager?.readManifest()?._package - if ((outerClass : PsiClass).getQualifiedName()?.startsWith(packageName ?: "") ?: false) - true else false - } - else false -} diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidXmlHandler.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidXmlHandler.kt index c2485cffa31..99ef5e6315c 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidXmlHandler.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidXmlHandler.kt @@ -20,7 +20,10 @@ import org.xml.sax.helpers.DefaultHandler import org.xml.sax.Attributes import java.util.HashMap -class AndroidXmlHandler(private val resourceManager: AndroidResourceManager, private val elementCallback: (String, String) -> Unit) : DefaultHandler() { +class AndroidXmlHandler( + private val resourceManager: AndroidResourceManager, + private val elementCallback: (String, String) -> Unit +) : DefaultHandler() { override fun startDocument() { super.startDocument() @@ -32,9 +35,9 @@ class AndroidXmlHandler(private val resourceManager: AndroidResourceManager, pri override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { val attributesMap = attributes.toMap() - val idAttr = attributesMap[resourceManager.idAttributeNoNamespace] - val classNameAttr = attributesMap[resourceManager.classAttributeNoNamespace] ?: localName - if (resourceManager.isResourceDeclarationOrUsage(idAttr)) elementCallback(resourceManager.idToName(idAttr), classNameAttr) + val idAttr = attributesMap[AndroidConst.ID_ATTRIBUTE_NO_NAMESPACE] + val classNameAttr = attributesMap[AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE] ?: localName + if (isResourceDeclarationOrUsage(idAttr)) elementCallback(idToName(idAttr), classNameAttr) } override fun endElement(uri: String?, localName: String, qName: String) { diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/CliAndroidResourceManager.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/CliAndroidResourceManager.kt index 961d1a5ec0f..a87b2f0eaac 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/CliAndroidResourceManager.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/CliAndroidResourceManager.kt @@ -23,35 +23,46 @@ import org.xml.sax.helpers.DefaultHandler import org.xml.sax.Attributes import javax.xml.parsers.SAXParser import javax.xml.parsers.SAXParserFactory +import kotlin.properties.Delegates -public class CliAndroidResourceManager(project: Project, searchPath: String?, private val manifestPath: String?) : org.jetbrains.jet.lang.resolve.android.AndroidResourceManagerBase(project, searchPath) { +public class CliAndroidResourceManager( + project: Project, + private val manifestPath: String, + private val mainResDirectory: String +) : AndroidResourceManager(project) { + + override val androidModuleInfo by Delegates.lazy { + AndroidModuleInfo(getApplicationPackage(manifestPath), mainResDirectory) + } val saxParser: SAXParser = initSAX() protected fun initSAX(): SAXParser { val saxFactory = SAXParserFactory.newInstance() - saxFactory?.setNamespaceAware(true) - return saxFactory!!.newSAXParser() + saxFactory.setNamespaceAware(true) + return saxFactory.newSAXParser() } - override fun readManifest(): org.jetbrains.jet.lang.resolve.android.AndroidManifest { + + private fun getApplicationPackage(manifestPath: String): String { try { - val manifestXml = File(manifestPath!!) - var _package: String = "" + val manifestXml = File(manifestPath) + var applicationPackage: String = "" try { saxParser.parse(FileInputStream(manifestXml), object : DefaultHandler() { override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) { if (localName == "manifest") - _package = attributes.toMap()["package"] ?: "" + applicationPackage = attributes.toMap()["package"] ?: "" } }) } catch (e: Exception) { throw e } - return org.jetbrains.jet.lang.resolve.android.AndroidManifest(_package) + return applicationPackage } catch (e: Exception) { - throw org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor.NoAndroidManifestFound() + throw AndroidUIXmlProcessor.NoAndroidManifestFound() } } + } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/CliAndroidUIXmlProcessor.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/CliAndroidUIXmlProcessor.kt index 56b1d940530..e92c1681e87 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/CliAndroidUIXmlProcessor.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/CliAndroidUIXmlProcessor.kt @@ -20,17 +20,21 @@ import java.util.ArrayList import com.intellij.openapi.project.Project import com.intellij.psi.PsiFile import java.io.ByteArrayInputStream +import kotlin.properties.Delegates -public class CliAndroidUIXmlProcessor(project: Project, override val searchPath: String?, val manifestPath: String?) : org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor(project) { +public class CliAndroidUIXmlProcessor( + project: Project, + private val manifestPath: String, + private val mainResDirectory: String +) : AndroidUIXmlProcessor(project) { - override var androidAppPackage: String = "" - get() = resourceManager.readManifest()._package + override val resourceManager: CliAndroidResourceManager by Delegates.lazy { + CliAndroidResourceManager(project, manifestPath, mainResDirectory) + } - override val resourceManager = org.jetbrains.jet.lang.resolve.android.CliAndroidResourceManager(project, searchPath, manifestPath) - - override fun parseSingleFileImpl(file: PsiFile): String { + override fun parseSingleFile(file: PsiFile): String { val ids: MutableCollection = ArrayList() - val handler = org.jetbrains.jet.lang.resolve.android.AndroidXmlHandler(resourceManager, { id, wClass -> ids.add(AndroidWidget(id, wClass)) }) + val handler = AndroidXmlHandler(resourceManager, { id, clazz -> ids.add(AndroidWidget(id, clazz)) }) try { val inputStream = ByteArrayInputStream(file.getVirtualFile().contentsToByteArray()) resourceManager.saxParser.parse(inputStream, handler) diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/KotlinWriter.kt b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/KotlinWriter.kt index 6cdd1ed291f..d1d27f9a878 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/KotlinWriter.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/KotlinWriter.kt @@ -29,12 +29,12 @@ class KotlinStringWriter : KotlinWriter { fun writeFunction(name: String, args: Collection?, retType: String, - stmts: Collection) { + statements: Collection) { val returnTerm = if (retType == "" || retType == "Unit") "" else ": $retType" val argStr = if (args != null) args.join(", ") else "" body.writeln("fun $name($argStr)$returnTerm {") body.incIndent() - for (stmt in stmts) + for (stmt in statements) body.writeln(stmt) body.decIndent() body.writeln("}") diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidConst.java b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/androidResources.kt similarity index 68% rename from plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidConst.java rename to plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/androidResources.kt index 6655adf453f..360d0202f89 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/AndroidConst.java +++ b/plugins/android-compiler-plugin/src/org/jetbrains/jet/lang/resolve/android/androidResources.kt @@ -14,11 +14,10 @@ * limitations under the License. */ -package org.jetbrains.jet.lang.resolve.android; +package org.jetbrains.jet.lang.resolve.android -import com.intellij.openapi.util.Key; +public data class AndroidModuleInfo(val applicationPackage: String, val mainResDirectory: String?) -public class AndroidConst { - public static final Key ANDROID_USER_PACKAGE = Key.create("ANDROID_USER_PACKAGE"); - public static final String SYNTHETIC_FILENAME = "ANDROIDXML.kt"; -} +trait AndroidResource + +public class AndroidWidget(val id: String, val className: String) : AndroidResource \ No newline at end of file diff --git a/plugins/android-compiler-plugin/tests/org/jetbrains/jet/lang/resolve/android/test/AbstractAndroidXml2KConversionTest.kt b/plugins/android-compiler-plugin/tests/org/jetbrains/jet/lang/resolve/android/test/AbstractAndroidXml2KConversionTest.kt index b0e39516294..fee72b066b7 100644 --- a/plugins/android-compiler-plugin/tests/org/jetbrains/jet/lang/resolve/android/test/AbstractAndroidXml2KConversionTest.kt +++ b/plugins/android-compiler-plugin/tests/org/jetbrains/jet/lang/resolve/android/test/AbstractAndroidXml2KConversionTest.kt @@ -37,11 +37,11 @@ public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() { public fun doTest(path: String) { val jetCoreEnvironment = getEnvironment(path) - val parser = CliAndroidUIXmlProcessor(jetCoreEnvironment.getProject(), path + "/layout", path + "AndroidManifest.xml") + val parser = CliAndroidUIXmlProcessor(jetCoreEnvironment.getProject(), path + "AndroidManifest.xml", path + "/layout") - val actual = parser.parseToString() + val actual = parser.parse() - JetTestUtils.assertEqualsToFile(File(path + "/layout.kt"), actual!!) + JetTestUtils.assertEqualsToFile(File(path + "/layout.kt"), actual) } public fun doNoManifestTest(path: String) { @@ -55,8 +55,6 @@ public abstract class AbstractAndroidXml2KConversionTest : UsefulTestCase() { private fun getEnvironment(testPath: String): JetCoreEnvironment { val configuration = JetTestUtils.compilerConfigurationForTests(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK) -// configuration.put(JVMConfigurationKeys.ANDROID_RES_PATH, testPath + "/layout") -// configuration.put(JVMConfigurationKeys.ANDROID_MANIFEST, testPath + "/AndroidManifest.xml") return JetCoreEnvironment.createForTests(getTestRootDisposable()!!, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) } } diff --git a/plugins/android-compiler-plugin/tests/org/jetbrains/jet/lang/resolve/android/test/CompilerTestUtils.kt b/plugins/android-compiler-plugin/tests/org/jetbrains/jet/lang/resolve/android/test/CompilerTestUtils.kt index d506a83ebba..8196e62fd71 100644 --- a/plugins/android-compiler-plugin/tests/org/jetbrains/jet/lang/resolve/android/test/CompilerTestUtils.kt +++ b/plugins/android-compiler-plugin/tests/org/jetbrains/jet/lang/resolve/android/test/CompilerTestUtils.kt @@ -36,8 +36,8 @@ private class AndroidTestExternalDeclarationsProvider( val manifestPath: String ) : ExternalDeclarationsProvider { override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection { - val parser = CliAndroidUIXmlProcessor(project, resPath, manifestPath) - return emptyOrSingletonList(parser.parseToPsi(project)) + val parser = CliAndroidUIXmlProcessor(project, manifestPath, resPath) + return emptyOrSingletonList(parser.parseToPsi()) } } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidGotoDeclarationHandler.kt b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidGotoDeclarationHandler.kt index 029c6d7fafc..6b92c474370 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidGotoDeclarationHandler.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidGotoDeclarationHandler.kt @@ -28,13 +28,13 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression import org.jetbrains.jet.lang.psi.JetProperty import com.intellij.psi.impl.light.LightElement import com.intellij.psi.xml.XmlAttribute -import org.jetbrains.jet.lang.resolve.android.isRClassField import com.intellij.psi.PsiField import com.intellij.openapi.module.ModuleServiceManager import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo import org.jetbrains.jet.plugin.caches.resolve.ModuleSourceInfo public class AndroidGotoDeclarationHandler : GotoDeclarationHandler { + override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array? { if (sourceElement is LeafPsiElement && sourceElement.getParent() is JetSimpleNameExpression) { val resolved = JetSimpleNameReference(sourceElement.getParent() as JetSimpleNameExpression).resolve() @@ -60,4 +60,5 @@ public class AndroidGotoDeclarationHandler : GotoDeclarationHandler { override fun getActionText(context: DataContext?): String? { return null } + } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidRenameProcessor.kt b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidRenameProcessor.kt index c9562217940..cc9b8b4f846 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidRenameProcessor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidRenameProcessor.kt @@ -29,22 +29,38 @@ import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper import org.jetbrains.android.util.AndroidResourceUtil import com.intellij.psi.xml.XmlAttribute import com.intellij.psi.impl.light.LightElement -import org.jetbrains.jet.lang.resolve.android.isRClassField import com.intellij.openapi.module.ModuleServiceManager import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo import org.jetbrains.jet.plugin.caches.resolve.ModuleSourceInfo import com.intellij.openapi.module.Module import org.jetbrains.jet.lang.psi.JetFile import org.jetbrains.jet.lang.psi.moduleInfo +import org.jetbrains.jet.lang.resolve.android.nameToIdDeclaration +import org.jetbrains.jet.lang.resolve.android.idToName +import com.intellij.psi.PsiField +import com.intellij.psi.PsiClass public class AndroidRenameProcessor : RenamePsiElementProcessor() { + override fun canProcessElement(element: PsiElement): Boolean { - // either renaming synthetic property, or value in ui xml, or R class field + // Either renaming synthetic property, or value in layout xml, or R class field return (element.namedUnwrappedElement is JetProperty && isAndroidSyntheticElement(element.namedUnwrappedElement)) || element is XmlAttributeValue || isRClassField(element) } + private fun isRClassField(element: PsiElement): Boolean { + return if (element is PsiField) { + val outerClass = element.getParent()?.getParent() + if (outerClass !is PsiClass) return false + + if (outerClass.getQualifiedName()?.startsWith(AndroidConst.SYNTHETIC_PACKAGE) ?: false) + true else false + } + else false + } + + private fun PsiElement.getModule(): Module? { val moduleInfo = getModuleInfo() if (moduleInfo is ModuleSourceInfo) return moduleInfo.module @@ -58,7 +74,12 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() { return null } - override fun prepareRenaming(element: PsiElement?, newName: String?, allRenames: MutableMap, scope: SearchScope) { + override fun prepareRenaming( + element: PsiElement?, + newName: String, + allRenames: MutableMap, + scope: SearchScope + ) { if (element != null && element.namedUnwrappedElement is JetProperty) { renameSyntheticProperty(element.namedUnwrappedElement as JetProperty, newName, allRenames, scope) } @@ -70,45 +91,66 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() { } } - private fun renameSyntheticProperty(jetProperty: JetProperty, newName: String?, allRenames: MutableMap, scope: SearchScope) { + private fun renameSyntheticProperty( + jetProperty: JetProperty, + newName: String, + allRenames: MutableMap, + scope: SearchScope + ) { val oldName = jetProperty.getName() val module = jetProperty.getModule() if (module == null) return val processor = ModuleServiceManager.getService(module, javaClass()) - val resourceManager = processor!!.resourceManager + val resourceManager = processor.resourceManager val attr = resourceManager.idToXmlAttribute(oldName) as XmlAttribute - allRenames[XmlAttributeValueWrapper(attr.getValueElement()!!)] = resourceManager.nameToIdDeclaration(newName!!) + allRenames[XmlAttributeValueWrapper(attr.getValueElement())] = nameToIdDeclaration(newName) val name = AndroidResourceUtil.getResourceNameByReferenceText(newName) for (resField in AndroidResourceUtil.findIdFields(attr)) { - allRenames.put(resField, AndroidResourceUtil.getFieldNameByResourceName(name!!)) + allRenames.put(resField, AndroidResourceUtil.getFieldNameByResourceName(name)) } } - private fun renameAttributeValue(attribute: XmlAttributeValue, newName: String?, allRenames: MutableMap, scope: SearchScope) { - val element1 = LazyValueResourceElementWrapper.computeLazyElement(attribute) - val module = attribute.getModule() + private fun renameAttributeValue( + attribute: XmlAttributeValue, + newName: String, + allRenames: MutableMap, + scope: SearchScope + ) { + val element = LazyValueResourceElementWrapper.computeLazyElement(attribute) + val module = attribute.getModule() ?: ModuleUtilCore.findModuleForFile( + attribute.getContainingFile().getVirtualFile(), attribute.getProject()) if (module == null) return val processor = ModuleServiceManager.getService(module, javaClass()) - if (element1 == null) return - val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()!!) - val newPropName = processor!!.resourceManager.idToName(newName!!) + if (element == null) return + val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()) + val newPropName = idToName(newName) renameSyntheticProperties(allRenames, newPropName, oldPropName, processor) } - private fun renameSyntheticProperties(allRenames: MutableMap, newPropName: String, oldPropName: String?, processor: AndroidUIXmlProcessor) { - val props = processor.lastCachedPsi?.findChildrenByClass(javaClass()) - val matchedProps = props?.filter { it.getName() == oldPropName } ?: arrayListOf() + private fun renameSyntheticProperties( + allRenames: MutableMap, + newPropName: String, + oldPropName: String, + processor: AndroidUIXmlProcessor + ) { + val props = processor.parseToPsi()?.flatMap { it.findChildrenByClass(javaClass()).toList() } + val matchedProps = props?.filter { it.getName() == oldPropName } ?: listOf() for (prop in matchedProps) { allRenames[prop] = newPropName } } - private fun renameLightClassField(field: LightElement, newName: String?, allRenames: MutableMap, scope: SearchScope) { + private fun renameLightClassField( + field: LightElement, + newName: String, + allRenames: MutableMap, + scope: SearchScope + ) { val oldName = field.getName() val processor = ServiceManager.getService(field.getProject(), javaClass()) - renameSyntheticProperties(allRenames, newName!!, oldName, processor!!) + renameSyntheticProperties(allRenames, newName, oldName, processor) } } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidSimpleNameReferenceExtension.kt b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidSimpleNameReferenceExtension.kt index 9bf079056e0..5fffbe78c2e 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidSimpleNameReferenceExtension.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidSimpleNameReferenceExtension.kt @@ -33,7 +33,7 @@ public class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension } if (isAndroidSyntheticElement(resolvedElement)) { if (element is ValueResourceElementWrapper) { - val resource = element.getValue()!! + val resource = element.getValue() return (resolvedElement as JetProperty).getName() == resource.substring(resource.indexOf('/') + 1) } } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidXmlVisitor.kt b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidXmlVisitor.kt index 77a16c5bda9..72171baf301 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidXmlVisitor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidXmlVisitor.kt @@ -22,8 +22,13 @@ import com.intellij.psi.xml.XmlElement import com.intellij.psi.xml.XmlTag import com.intellij.psi.xml.XmlAttribute import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager +import org.jetbrains.jet.lang.resolve.android.idToName +import org.jetbrains.jet.lang.resolve.android.AndroidConst -class AndroidXmlVisitor(val resourceManager: AndroidResourceManager, val elementCallback: (String, String, XmlAttribute) -> Unit) : XmlElementVisitor() { +class AndroidXmlVisitor( + val resourceManager: AndroidResourceManager, + val elementCallback: (String, String, XmlAttribute) -> Unit +) : XmlElementVisitor() { override fun visitElement(element: PsiElement) { element.acceptChildren(this) @@ -34,10 +39,13 @@ class AndroidXmlVisitor(val resourceManager: AndroidResourceManager, val element } override fun visitXmlTag(tag: XmlTag?) { - val attribute = tag?.getAttribute(resourceManager.idAttribute) - if (attribute != null && attribute.getValue() != null) { - val classNameAttr = tag?.getAttribute(resourceManager.classAttributeNoNamespace)?.getValue() ?: tag?.getLocalName() - elementCallback(resourceManager.idToName(attribute.getValue()), classNameAttr!!, attribute) + val attribute = tag?.getAttribute(AndroidConst.ID_ATTRIBUTE) + if (attribute != null) { + val attributeValue = attribute.getValue() + if (attributeValue != null) { + val classNameAttr = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.getValue() ?: tag?.getLocalName() + elementCallback(idToName(attributeValue), classNameAttr!!, attribute) + } } tag?.acceptChildren(this) } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidExternalDeclarationsProvider.kt b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidExternalDeclarationsProvider.kt index 147201c8656..a0e9b20a25b 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidExternalDeclarationsProvider.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidExternalDeclarationsProvider.kt @@ -32,7 +32,7 @@ public class IDEAndroidExternalDeclarationsProvider(private val project: Project val module = moduleInfo.module val parser = ModuleServiceManager.getService(module, javaClass()) - val syntheticFile = parser.parseToPsi(project) + val syntheticFile = parser.parseToPsi() syntheticFile?.moduleInfo = moduleInfo return if (syntheticFile != null) listOf(syntheticFile) else listOf() diff --git a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidResourceManager.kt b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidResourceManager.kt index 2d1b4bfea05..60c7d426640 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidResourceManager.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidResourceManager.kt @@ -17,36 +17,23 @@ package org.jetbrains.jet.plugin.android import com.intellij.openapi.project.Project -import org.jetbrains.jet.lang.resolve.android.AndroidResourceManagerBase import com.intellij.psi.PsiElement import java.util.HashMap import com.intellij.psi.xml.XmlAttribute import com.intellij.psi.PsiFile import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.jet.lang.resolve.android.AndroidManifest import com.intellij.openapi.module.ModuleManager import java.util.ArrayList import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.module.Module +import com.intellij.psi.PsiManager +import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager +import org.jetbrains.jet.lang.resolve.android.AndroidModuleInfo +import kotlin.properties.Delegates -public class IDEAndroidResourceManager(val module: Module, searchPath: String?) : AndroidResourceManagerBase(module.getProject(), searchPath) { +public class IDEAndroidResourceManager(val module: Module) : AndroidResourceManager(module.getProject()) { - override fun getLayoutXmlFiles(): Collection { - val directories = getAndroidFacet()?.getAllResourceDirectories() ?: listOf() - return directories.flatMap { - (it.findChild("layout")?.getChildren() ?: array()).map { virtualFileToPsi(it)!! } - } - } - - private fun getAndroidFacet(): AndroidFacet? { - return AndroidFacet.getInstance(module) - } - - override fun readManifest(): AndroidManifest { - val facet = getAndroidFacet() - val attributeValue = facet?.getManifest()!!.getPackage() - return AndroidManifest(attributeValue.getRawText()) - } + override val androidModuleInfo: AndroidModuleInfo? by Delegates.lazy { module.androidFacet?.toAndroidModuleInfo() } override fun idToXmlAttribute(id: String): PsiElement? { var ret: PsiElement? = null @@ -58,4 +45,13 @@ public class IDEAndroidResourceManager(val module: Module, searchPath: String?) return ret } + private val Module.androidFacet: AndroidFacet? + get() = AndroidFacet.getInstance(this) + + private fun AndroidFacet.toAndroidModuleInfo(): AndroidModuleInfo { + val applicationPackage = getManifest().getPackage().toString() + val mainResDirectory = getAllResourceDirectories().firstOrNull()?.getPath() + return AndroidModuleInfo(applicationPackage, mainResDirectory) + } + } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidUIXmlProcessor.kt b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidUIXmlProcessor.kt index 734e59eb0fd..bd26da7a006 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidUIXmlProcessor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/IDEAndroidUIXmlProcessor.kt @@ -28,18 +28,16 @@ import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager import com.intellij.openapi.module.Module class IDEAndroidUIXmlProcessor(val module: Module) : AndroidUIXmlProcessor(module.getProject()) { - override val searchPath: String? = project.getBasePath() + "/res/layout/" - override var androidAppPackage: String = "" - get() = resourceManager.readManifest()._package - override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(module, searchPath) + override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(module) - override fun parseSingleFileImpl(file: PsiFile): String { - val ids: MutableCollection = ArrayList() + override fun parseSingleFile(file: PsiFile): List { + val widgets = arrayListOf() file.accept(AndroidXmlVisitor(resourceManager, { id, wClass, valueElement -> - ids.add(AndroidWidget(id, wClass)) + widgets.add(AndroidWidget(id, wClass)) })) - return produceKotlinProperties(KotlinStringWriter(), ids).toString() - } -} + return widgets + } + +} \ No newline at end of file diff --git a/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractAndroidFindUsagesTest.kt b/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractAndroidFindUsagesTest.kt index a54da3b103d..2bf3bfb8a4f 100644 --- a/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractAndroidFindUsagesTest.kt +++ b/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractAndroidFindUsagesTest.kt @@ -20,6 +20,7 @@ import org.jetbrains.jet.plugin.PluginTestCaseBase import kotlin.test.assertTrue import com.intellij.codeInsight.TargetElementUtilBase import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction +import kotlin.test.assertNotNull public abstract class AbstractAndroidFindUsagesTest : KotlinAndroidTestCase() { @@ -32,7 +33,10 @@ public abstract class AbstractAndroidFindUsagesTest : KotlinAndroidTestCase() { f.configureFromExistingVirtualFile(virtualFile) val targetElement = TargetElementUtilBase.findTargetElement(f.getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED or TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED) - val propUsages = f.findUsages(targetElement!!) + + assertNotNull(targetElement) + + val propUsages = f.findUsages(targetElement) assertTrue(propUsages.notEmpty) } diff --git a/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractAndroidRenameTest.kt b/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractAndroidRenameTest.kt index 7d3deb159c7..f2fb4fe05d8 100644 --- a/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractAndroidRenameTest.kt +++ b/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractAndroidRenameTest.kt @@ -24,6 +24,7 @@ import com.intellij.refactoring.rename.RenameProcessor import org.jetbrains.jet.plugin.PluginTestCaseBase import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction import kotlin.test.assertEquals +import kotlin.test.assertTrue import com.intellij.psi.PsiElement import org.jetbrains.jet.lang.psi.JetProperty @@ -42,9 +43,10 @@ public abstract class AbstractAndroidRenameTest : KotlinAndroidTestCase() { val completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, file) val element = TargetElementUtilBase.findTargetElement(completionEditor, TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED or TargetElementUtilBase.ELEMENT_NAME_ACCEPTED) assert(element != null) + assertTrue(element is JetProperty) // rename xml attribute by property - renameElementWithTextOccurences(element!!, NEW_NAME) + renameElementWithTextOccurences(element, NEW_NAME) val resolved = GotoDeclarationAction.findTargetElement(f.getProject(), f.getEditor(), f.getCaretOffset()) assertEquals("\"@+id/$NEW_NAME\"", resolved?.getText()) diff --git a/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractParserResultEqualityTest.kt b/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractParserResultEqualityTest.kt index 261e46011a8..ca77ccf2b24 100644 --- a/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractParserResultEqualityTest.kt +++ b/plugins/android-idea-plugin/tests/org/jetbrains/jet/android/AbstractParserResultEqualityTest.kt @@ -32,14 +32,14 @@ import com.intellij.openapi.module.ModuleManager public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase() { public fun doTest(path: String) { - val project = myFixture!!.getProject() + val project = myFixture.getProject() project.putUserData(TestConst.TESTDATA_PATH, path) - myFixture!!.copyDirectoryToProject(getResDir()!!, "res") - val cliParser = CliAndroidUIXmlProcessor(project, path + getResDir() + "/layout/", path + "../AndroidManifest.xml") + myFixture.copyDirectoryToProject(getResDir(), "res") + val cliParser = CliAndroidUIXmlProcessor(project, path + "../AndroidManifest.xml", path + getResDir() + "/layout/") val ideParser = IDEAndroidUIXmlProcessor(ModuleManager.getInstance(project).getModules()[0]) - val cliResult = cliParser.parseToPsi(project)!!.getText() - val ideResult = ideParser.parseToPsi(project)!!.getText() + val cliResult = cliParser.parseToPsi()!!.getText() + val ideResult = ideParser.parseToPsi()!!.getText() assertEquals(cliResult, ideResult) }