From 7536170e1de89c1769bd1bab9dda0e5a7ab9efce Mon Sep 17 00:00:00 2001 From: Mikhail Mutcianko Date: Wed, 23 Jul 2014 18:45:58 +0400 Subject: [PATCH] add android manifest support --- .../resolve/android/AndroidUIXmlParser.kt | 39 ++++++++++++++++++- .../jet/lang/resolve/android/AndroidUtil.kt | 2 + .../resolve/android/CliAndroidUIXmlParser.kt | 3 ++ .../plugin/android/IDEAndroidUIXmlParser.kt | 2 + 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/AndroidUIXmlParser.kt b/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/AndroidUIXmlParser.kt index b2dcea23d6a..9071d4a6982 100644 --- a/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/AndroidUIXmlParser.kt +++ b/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/AndroidUIXmlParser.kt @@ -15,17 +15,30 @@ import com.intellij.openapi.vfs.VirtualFileAdapter import com.intellij.openapi.vfs.VirtualFileEvent import com.intellij.openapi.project.Project import java.util.concurrent.ConcurrentLinkedQueue +import com.intellij.openapi.util.Key +import com.intellij.testFramework.LightVirtualFile +import com.intellij.openapi.vfs.VirtualFileSystem +import com.intellij.psi.PsiManager +import java.io.FileInputStream +import org.xml.sax.helpers.DefaultHandler +import org.xml.sax.Attributes +import org.jetbrains.kotlin.resolve.android.AndroidConst.* +import com.intellij.psi.PsiFileFactory abstract class AndroidUIXmlParser { inner class NoUIXMLsFound: Exception("No android UI xmls found in $searchPath") + class NoAndroidManifestFound: Exception("No android manifest file found in project root") + class ManifestParsingFailed enum class CacheAction { HIT; MISS } val androidImports = arrayListOf("android.app.Activity", "android.view.View", "android.widget.*") + abstract val searchPath: String? + abstract val androidAppPackage: String val saxParser = initSAX() @@ -48,7 +61,10 @@ abstract class AndroidUIXmlParser { if (cacheState == null) return null return if (cacheState == CacheAction.MISS || lastCachedPsi == null) { try { - val psiFile = JetPsiFactory(project).createFile(renderString()) + val vf = LightVirtualFile("ANDROIDXML.kt", renderString()) + val psiFile = PsiManager.getInstance(project).findFile(vf) as JetFile + psiFile.putUserData(ANDROID_SYNTHETIC, "OK") + psiFile.putUserData(ANDROID_USER_PACKAGE, androidAppPackage) lastCachedPsi = psiFile psiFile } catch (e: Exception) { @@ -87,6 +103,7 @@ abstract class AndroidUIXmlParser { } private fun writeImports(kw: KotlinStringWriter): KotlinWriter { + kw.writePackage(androidAppPackage) for (elem in androidImports) kw.writeImport(elem) kw.writeEmptyLine() @@ -146,6 +163,26 @@ abstract class AndroidUIXmlParser { protected abstract fun lazySetup() + protected fun readManifest(): AndroidManifest { + try { + val manifestXml = File(searchPath!!).getParentFile()!!.getParentFile()!!.listFiles { it.name == "AndroidManifest.xml" }!!.first() + var _package: 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"] ?: "" + } + }) + } catch (e: Exception) { + throw e + } + return AndroidManifest(_package) + } catch (e: Exception) { + throw NoAndroidManifestFound() + } + } + private fun produceKotlinProperties(kw: KotlinStringWriter, ids: Collection): StringBuffer { for (id in ids) { val body = arrayListOf("return findViewById(0) as ${id.className}") diff --git a/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/AndroidUtil.kt b/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/AndroidUtil.kt index a3d5949f971..d610b885eec 100644 --- a/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/AndroidUtil.kt +++ b/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/AndroidUtil.kt @@ -16,3 +16,5 @@ class AndroidID(val rawID: String): AndroidResource { } class AndroidWidget(val id: String, val className: String): AndroidResource + +class AndroidManifest(val _package: String): AndroidResource \ No newline at end of file diff --git a/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/CliAndroidUIXmlParser.kt b/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/CliAndroidUIXmlParser.kt index 2ab9333a9c9..33180a637a1 100644 --- a/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/CliAndroidUIXmlParser.kt +++ b/compiler/frontend.android/src/org/jetbrains/jet/lang/resolve/android/CliAndroidUIXmlParser.kt @@ -6,10 +6,13 @@ import com.intellij.openapi.project.Project class CliAndroidUIXmlParser(val project: Project, override val searchPath: String?): AndroidUIXmlParser() { + override var androidAppPackage: String = "" + override fun lazySetup() { val fileManager = VirtualFileManager.getInstance() val watchDir = fileManager.findFileByUrl("file://" + searchPath) filesToProcess.addAll(watchDir?.getChildren()?.toArrayList() ?: ArrayList(0)) + androidAppPackage = readManifest()._package } } diff --git a/idea/src/org/jetbrains/jet/plugin/android/IDEAndroidUIXmlParser.kt b/idea/src/org/jetbrains/jet/plugin/android/IDEAndroidUIXmlParser.kt index ebd30311acc..d8820e399fe 100644 --- a/idea/src/org/jetbrains/jet/plugin/android/IDEAndroidUIXmlParser.kt +++ b/idea/src/org/jetbrains/jet/plugin/android/IDEAndroidUIXmlParser.kt @@ -9,9 +9,11 @@ import com.intellij.openapi.vfs.VirtualFileEvent class IDEAndroidUIXmlParser(project: Project): AndroidUIXmlParser() { override val searchPath: String? = project.getBasePath() + "/res/layout/" + override var androidAppPackage: String = "" override protected fun lazySetup() { if (listenerSetUp) return + androidAppPackage = readManifest()._package val fileManager = VirtualFileManager.getInstance() val watchDir = fileManager.findFileByUrl("file://" + searchPath) filesToProcess.addAll(watchDir?.getChildren()?.toArrayList() ?: ArrayList(0))