frontend.android renamed to android-compiler-plugin
This commit is contained in:
committed by
Yan Zhulanow
parent
35028227a0
commit
565ce5a781
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 class AndroidConst {
|
||||
public static final Key<String> ANDROID_USER_PACKAGE = Key.create("ANDROID_USER_PACKAGE");
|
||||
public static final String SYNTHETIC_FILENAME = "ANDROIDXML.kt";
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.PsiFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
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
|
||||
|
||||
abstract fun getLayoutXmlFiles(): Collection<PsiFile>
|
||||
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 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")
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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<PsiFile> {
|
||||
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 } ?: ArrayList(0)
|
||||
return files.sortBy({it.getName()})
|
||||
}
|
||||
|
||||
protected fun vritualFileToPsi(vf: VirtualFile): PsiFile? {
|
||||
val psiManager = PsiManager.getInstance(project)
|
||||
return psiManager.findFile(vf)
|
||||
|
||||
}
|
||||
|
||||
override fun idToXmlAttribute(id: String): PsiElement? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.io.File
|
||||
import javax.xml.parsers.SAXParserFactory
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import javax.xml.parsers.SAXParser
|
||||
import java.util.HashMap
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
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.psi.PsiManager
|
||||
import java.io.FileInputStream
|
||||
import org.xml.sax.helpers.DefaultHandler
|
||||
import org.xml.sax.Attributes
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
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.*
|
||||
|
||||
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 = arrayListOf("android.app.Activity",
|
||||
"android.view.View",
|
||||
"android.widget.*")
|
||||
|
||||
protected abstract val searchPath: String?
|
||||
protected abstract val androidAppPackage: String
|
||||
|
||||
private val fileCache = HashMap<PsiFile, String>()
|
||||
var lastCachedPsi: JetFile? = null
|
||||
private set
|
||||
protected val fileModificationTime: HashMap<PsiFile, Long> = HashMap()
|
||||
|
||||
protected val filesToProcess: Queue<PsiFile> = ConcurrentLinkedQueue()
|
||||
|
||||
public abstract val resourceManager: AndroidResourceManager
|
||||
|
||||
protected val LOG: Logger = Logger.getInstance(this.javaClass)
|
||||
|
||||
public fun parseToString(): String? {
|
||||
val cacheState = doParse()
|
||||
if (cacheState == null) return null
|
||||
return renderString()
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
private fun writeImports(kw: KotlinStringWriter): KotlinWriter {
|
||||
kw.writePackage(androidAppPackage)
|
||||
for (elem in androidImports)
|
||||
kw.writeImport(elem)
|
||||
kw.writeEmptyLine()
|
||||
return kw
|
||||
}
|
||||
|
||||
private fun parseSingleFileWithCache(file: PsiFile): Pair<String, CacheAction> {
|
||||
val lastRecorded = fileModificationTime[file] ?: -1
|
||||
if (file.getModificationStamp() > lastRecorded)
|
||||
return Pair(parseSingleFile(file), CacheAction.MISS)
|
||||
else
|
||||
return Pair(fileCache[file]!!, CacheAction.HIT)
|
||||
}
|
||||
|
||||
private fun parseSingleFile(file: PsiFile): String {
|
||||
val res = parseSingleFileImpl(file)
|
||||
fileModificationTime[file] = file.getModificationStamp()
|
||||
fileCache[file] = res
|
||||
return res
|
||||
}
|
||||
|
||||
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<AndroidWidget>): 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()
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.PsiFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import java.util.ArrayList
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.PsiClass
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidWidget(val id: String, val className: String) : AndroidResource
|
||||
|
||||
class AndroidManifest(val _package: String) : AndroidResource
|
||||
|
||||
fun isAndroidSyntheticFile(f: PsiFile?): Boolean {
|
||||
return f?.getUserData(org.jetbrains.jet.lang.resolve.android.AndroidConst.ANDROID_USER_PACKAGE) != null
|
||||
}
|
||||
|
||||
public fun isAndroidSyntheticElement(element: PsiElement?): Boolean {
|
||||
return isAndroidSyntheticFile(element?.getContainingFile())
|
||||
}
|
||||
|
||||
public fun searchAndAddAndroidDeclarations(project: Project, originalFiles: Collection<JetFile>): Collection<JetFile> {
|
||||
val parser = ServiceManager.getService<AndroidUIXmlProcessor>(project, javaClass<AndroidUIXmlProcessor>())
|
||||
val file = parser?.parseToPsi(project)
|
||||
val files = ArrayList(originalFiles)
|
||||
if (file != null) files.add(file)
|
||||
return files
|
||||
}
|
||||
|
||||
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<AndroidUIXmlProcessor>(element.getProject(), javaClass<AndroidUIXmlProcessor>())
|
||||
val packageName = processor?.resourceManager?.readManifest()?._package
|
||||
if ((outerClass as PsiClass).getQualifiedName()?.startsWith(packageName ?: "") ?: false)
|
||||
true else false
|
||||
}
|
||||
else false
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 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() {
|
||||
|
||||
override fun startDocument() {
|
||||
super<DefaultHandler>.startDocument()
|
||||
}
|
||||
|
||||
override fun endDocument() {
|
||||
super<DefaultHandler>.endDocument()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
override fun endElement(uri: String?, localName: String, qName: String) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public fun Attributes.toMap(): HashMap<String, String> {
|
||||
val res = HashMap<String, String>()
|
||||
for (index in 0..getLength() - 1) {
|
||||
val attrName = getLocalName(index)!!
|
||||
val attrVal = getValue(index)!!
|
||||
res[attrName] = attrVal
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.project.Project
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import org.xml.sax.helpers.DefaultHandler
|
||||
import org.xml.sax.Attributes
|
||||
import javax.xml.parsers.SAXParser
|
||||
import javax.xml.parsers.SAXParserFactory
|
||||
|
||||
public class CliAndroidResourceManager(project: Project, searchPath: String?, private val manifestPath: String?) : org.jetbrains.jet.lang.resolve.android.AndroidResourceManagerBase(project, searchPath) {
|
||||
|
||||
val saxParser: SAXParser = initSAX()
|
||||
|
||||
protected fun initSAX(): SAXParser {
|
||||
val saxFactory = SAXParserFactory.newInstance()
|
||||
saxFactory?.setNamespaceAware(true)
|
||||
return saxFactory!!.newSAXParser()
|
||||
}
|
||||
override fun readManifest(): org.jetbrains.jet.lang.resolve.android.AndroidManifest {
|
||||
try {
|
||||
val manifestXml = File(manifestPath!!)
|
||||
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 org.jetbrains.jet.lang.resolve.android.AndroidManifest(_package)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
throw org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor.NoAndroidManifestFound()
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFile
|
||||
|
||||
public class CliAndroidUIXmlProcessor(project: Project, override val searchPath: String?, val manifestPath: String?) : org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor(project) {
|
||||
|
||||
override var androidAppPackage: String = ""
|
||||
get() = resourceManager.readManifest()._package
|
||||
|
||||
override val resourceManager = org.jetbrains.jet.lang.resolve.android.CliAndroidResourceManager(project, searchPath, manifestPath)
|
||||
|
||||
override fun parseSingleFileImpl(file: PsiFile): String {
|
||||
val ids: MutableCollection<AndroidWidget> = ArrayList()
|
||||
val handler = org.jetbrains.jet.lang.resolve.android.AndroidXmlHandler(resourceManager, { id, wClass -> ids.add(AndroidWidget(id, wClass)) })
|
||||
try {
|
||||
resourceManager.saxParser.parse(file.getVirtualFile()?.getInputStream()!!, handler)
|
||||
return produceKotlinProperties(KotlinStringWriter(), ids).toString()
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
LOG.error(e)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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 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")
|
||||
|
||||
val indentUnit = " "
|
||||
protected var currentIndent: String = indentUnit.repeat(indentDepth)
|
||||
private val children = ArrayList<Context>()
|
||||
|
||||
public fun incIndent() {
|
||||
indentDepth++
|
||||
currentIndent += indentUnit
|
||||
}
|
||||
|
||||
public fun decIndent() {
|
||||
indentDepth--
|
||||
if (indentDepth < 0)
|
||||
throw InvalidIndent(indentDepth)
|
||||
currentIndent = currentIndent.substring(0, currentIndent.length - indentUnit.length)
|
||||
}
|
||||
|
||||
public open fun write(what: String) {
|
||||
writeNoIndent(currentIndent)
|
||||
writeNoIndent(what)
|
||||
}
|
||||
|
||||
public fun writeNoIndent(what: String) {
|
||||
buffer.append(what)
|
||||
}
|
||||
|
||||
public fun writeln(what: String) {
|
||||
write(what)
|
||||
newLine()
|
||||
}
|
||||
|
||||
public fun newLine() {
|
||||
writeNoIndent("\n")
|
||||
}
|
||||
|
||||
|
||||
public fun trim(num: Int) {
|
||||
buffer.delete(buffer.length - num, buffer.length)
|
||||
}
|
||||
|
||||
public fun fork(newBuffer: StringBuffer = StringBuffer(),
|
||||
newIndentDepth: Int = indentDepth): Context {
|
||||
val child = Context(newBuffer, newIndentDepth)
|
||||
children.add(child)
|
||||
return child
|
||||
}
|
||||
|
||||
public fun adopt<T : Context>(c: T, inheritIndent: Boolean = true): T {
|
||||
children.add(c)
|
||||
if (inheritIndent) c.currentIndent = currentIndent
|
||||
return c
|
||||
}
|
||||
|
||||
public fun absorbChildren(noIndent: Boolean = true) {
|
||||
for (child in children) {
|
||||
child.absorbChildren()
|
||||
if (noIndent)
|
||||
writeNoIndent(child.toString())
|
||||
else
|
||||
write(child.toString())
|
||||
}
|
||||
children.clear()
|
||||
}
|
||||
|
||||
public override fun toString(): String {
|
||||
return buffer.toString()
|
||||
}
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
trait KotlinWriter {
|
||||
fun output(): StringBuffer
|
||||
}
|
||||
|
||||
class KotlinStringWriter : KotlinWriter {
|
||||
|
||||
private val ctx = org.jetbrains.jet.lang.resolve.android.Context()
|
||||
private val imports = ctx.fork()
|
||||
private val body = ctx.fork()
|
||||
|
||||
fun writeFunction(name: String,
|
||||
args: Collection<String>?,
|
||||
retType: String,
|
||||
stmts: Collection<String>) {
|
||||
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)
|
||||
body.writeln(stmt)
|
||||
body.decIndent()
|
||||
body.writeln("}")
|
||||
}
|
||||
|
||||
fun writeExtensionFunction(receiver: String,
|
||||
name: String,
|
||||
args: Collection<String>?,
|
||||
retType: String,
|
||||
body: Collection<String>) {
|
||||
writeFunction("$receiver.$name", args, retType, body)
|
||||
}
|
||||
|
||||
fun writeImmutableProperty(name: String,
|
||||
retType: String,
|
||||
getterBody: Collection<String>) {
|
||||
body.writeln("val $name: $retType")
|
||||
body.incIndent()
|
||||
body.write("get() ")
|
||||
if (getterBody.size > 1) {
|
||||
body.writeNoIndent("{\n")
|
||||
body.incIndent()
|
||||
for (stmt in getterBody) {
|
||||
body.writeln(stmt)
|
||||
}
|
||||
body.decIndent()
|
||||
body.writeln("}")
|
||||
}
|
||||
else {
|
||||
body.writeNoIndent("=")
|
||||
body.writeNoIndent(getterBody.join("").replace("return", ""))
|
||||
body.newLine()
|
||||
}
|
||||
body.decIndent()
|
||||
body.newLine()
|
||||
}
|
||||
|
||||
fun writeImmutableExtensionProperty(receiver: String,
|
||||
name: String,
|
||||
retType: String,
|
||||
getterBody: Collection<String>) {
|
||||
writeImmutableProperty("$receiver.$name", retType, getterBody)
|
||||
}
|
||||
|
||||
fun writeImport(what: String) {
|
||||
imports.writeln("import $what")
|
||||
}
|
||||
|
||||
fun writePackage(_package: String) {
|
||||
ctx.writeln("package $_package\n")
|
||||
}
|
||||
|
||||
fun writeEmptyLine() {
|
||||
body.newLine()
|
||||
}
|
||||
|
||||
override fun output(): StringBuffer {
|
||||
ctx.absorbChildren()
|
||||
return ctx.buffer
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user