auto cast widget to its original type

- change property return type signatures from View to actual widget type
- simplify and update tests
This commit is contained in:
Mikhail Mutcianko
2014-07-14 15:39:43 +04:00
committed by Yan Zhulanow
parent 31dc8194f1
commit aa01d6d7cf
8 changed files with 67 additions and 67 deletions
@@ -11,10 +11,11 @@ import org.jetbrains.jet.lang.psi.JetPsiFactory
class AndroidUIXmlParser(val project: Project?, val searchPaths: Collection<File>) {
val ids: MutableCollection<AndroidID> = ArrayList()
val ids: MutableCollection<AndroidWidget> = ArrayList()
val kw = KotlinStringWriter()
val androidImports = arrayListOf("android.app.Activity",
"android.view.View")
"android.view.View",
"android.widget.*")
public fun parse(): String {
doParse()
@@ -53,19 +54,23 @@ class AndroidUIXmlParser(val project: Project?, val searchPaths: Collection<File
val factory = SAXParserFactory.newInstance()
factory?.setNamespaceAware(true)
val parser = factory!!.newSAXParser() // TODO: annotate this
val handler = AndroidXmlHandler({ id -> ids.add(AndroidID(id)) })
val handler = AndroidXmlHandler({ id, wClass -> widgetCallback(id, wClass) })
writeImports()
for (xmlStream in xmlStreams) {
parser.parse(xmlStream, handler)
}
}
private fun widgetCallback(id: String, className: String) {
ids.add(AndroidWidget(id, className))
}
private fun produceKotlinSignatures(): StringBuffer {
for (id in ids) {
val body = arrayListOf("return findViewById(R.id.${id.toString()})!!")
val body = arrayListOf("return findViewById(R.id.${id.id}) as ${id.className}")
kw.writeImmutableExtensionProperty(receiver = "Activity",
name = id.toString(),
retType = "View",
name = id.id,
retType = id.className,
getterBody = body )
}
return kw.output()
@@ -15,3 +15,4 @@ class AndroidID(val rawID: String): AndroidResource {
}
}
class AndroidWidget(val id: String, val className: String): AndroidResource
@@ -4,7 +4,7 @@ import org.xml.sax.helpers.DefaultHandler
import org.xml.sax.Attributes
import java.util.HashMap
class AndroidXmlHandler(val idCallback: (String)-> Unit): DefaultHandler() {
class AndroidXmlHandler(val elementCallback: (String, String)-> Unit): DefaultHandler() {
override fun startDocument() {
super<DefaultHandler>.startDocument()
@@ -18,7 +18,8 @@ class AndroidXmlHandler(val idCallback: (String)-> Unit): DefaultHandler() {
val hashMap = attributes.toMap()
val s = hashMap["id"]
val idPrefix = "@+id/"
if (s != null && s.startsWith(idPrefix)) idCallback(s.replace(idPrefix, ""))
val className = hashMap["class"] ?: localName
if (s != null && s.startsWith(idPrefix)) elementCallback(s.replace(idPrefix, ""), className)
}
override fun endElement(uri: String?, localName: String, qName: String) {
@@ -5,19 +5,21 @@ trait KotlinWriter
class KotlinStringWriter : KotlinWriter {
val ctx = Context()
val imports = ctx.fork()
val body = ctx.fork()
fun writeFunction(name: String,
args: Collection<String>?,
retType: String,
body: Collection<String>) {
stmts: Collection<String>) {
val returnTerm = if (retType == "" || retType == "Unit") "" else ": $retType"
val argStr = if (args != null) args.join(", ") else ""
ctx.writeln("fun $name($argStr)$returnTerm {")
ctx.incIndent()
for (stmt in body)
ctx.writeln(stmt)
ctx.decIndent()
ctx.writeln("}")
body.writeln("fun $name($argStr)$returnTerm {")
body.incIndent()
for (stmt in stmts)
body.writeln(stmt)
body.decIndent()
body.writeln("}")
}
fun writeExtensionFunction(receiver: String,
@@ -31,24 +33,24 @@ class KotlinStringWriter : KotlinWriter {
fun writeImmutableProperty(name: String,
retType: String,
getterBody: Collection<String>) {
ctx.writeln("val $name: $retType")
ctx.incIndent()
ctx.write("get() ")
body.writeln("val $name: $retType")
body.incIndent()
body.write("get() ")
if (getterBody.size > 1) {
ctx.writeNoIndent("{\n")
ctx.incIndent()
body.writeNoIndent("{\n")
body.incIndent()
for (stmt in getterBody) {
ctx.writeln(stmt)
body.writeln(stmt)
}
ctx.decIndent()
ctx.writeln("}")
body.decIndent()
body.writeln("}")
} else {
ctx.writeNoIndent("=")
ctx.writeNoIndent(getterBody.join("").replace("return", ""))
ctx.newLine()
body.writeNoIndent("=")
body.writeNoIndent(getterBody.join("").replace("return", ""))
body.newLine()
}
ctx.decIndent()
ctx.newLine()
body.decIndent()
body.newLine()
}
fun writeImmutableExtensionProperty(receiver: String,
@@ -59,13 +61,16 @@ class KotlinStringWriter : KotlinWriter {
}
fun writeImport(what: String) {
ctx.writeln("import $what")
imports.writeln("import $what")
}
fun writeEmptyLine() {
ctx.newLine()
body.newLine()
}
fun output() = ctx.buffer
fun output(): StringBuffer {
ctx.absorbChildren()
return ctx.buffer
}
}
@@ -1,21 +1,16 @@
import android.app.Activity
import android.view.View
import android.widget.*
val Activity.item_detail_container: View
get() = findViewById(R.id.item_detail_container)!!
val Activity.item_detail_container: FrameLayout
get() = findViewById(R.id.item_detail_container) as FrameLayout
val Activity.textView1: View
get() = findViewById(R.id.textView1)!!
val Activity.textView1: TextView
get() = findViewById(R.id.textView1) as TextView
val Activity.password: View
get() = findViewById(R.id.password)!!
val Activity.password: EditText
get() = findViewById(R.id.password) as EditText
val Activity.textView2: View
get() = findViewById(R.id.textView2)!!
val Activity.passwordConfirmation: View
get() = findViewById(R.id.passwordConfirmation)!!
val Activity.login: View
get() = findViewById(R.id.login)!!
val Activity.login: Button
get() = findViewById(R.id.login) as Button
@@ -18,22 +18,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword" >
<requestFocus />
</EditText>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Repeat your password" />
<EditText
android:id="@+id/passwordConfirmation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword" />
<Button
@@ -0,0 +1,6 @@
package android.widget
class EditText
class TextView
class Button
class FrameLayout
@@ -20,8 +20,9 @@ import java.util.Scanner;
public class AndroidXmlTest extends TestCaseWithTmpdir {
private final File singleFile = new File(getTestDataPath() + "/converter/singleFile/layout.xml");
private final File fakeActivity = new File(getTestDataPath() + "/fakeHelpers/Activity.kt");
private final File fakeView = new File(getTestDataPath() + "/fakeHelpers/View.kt");
private final File fakeActivitySrc = new File(getTestDataPath() + "/fakeHelpers/Activity.kt");
private final File fakeViewSrc = new File(getTestDataPath() + "/fakeHelpers/View.kt");
private final File fakeWidgetsSrc = new File(getTestDataPath() + "/fakeHelpers/Widgets.kt");
@Override
public void setUp() throws Exception {
@@ -54,15 +55,17 @@ public class AndroidXmlTest extends TestCaseWithTmpdir {
JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(getTestRootDisposable(),
ConfigurationKind.ALL);
JetFile psiFile = JetTestUtils.createFile(singleFile.getName(), text, jetCoreEnvironment.getProject());
JetFile fakeActivityClass = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeActivity);
JetFile fakeViewClass = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeView);
JetFile fakeActivity = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeActivitySrc);
JetFile fakeView = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeViewSrc);
JetFile fakeWidgets = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeWidgetsSrc);
JetFile fakeRClass = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(),
new File(getTestDataPath() + "/converter/singleFile/R.kt"));
List<JetFile> files = new ArrayList<JetFile>();
files.add(psiFile);
files.add(fakeActivityClass);
files.add(fakeViewClass);
files.add(fakeActivity);
files.add(fakeView);
files.add(fakeRClass);
files.add(fakeWidgets);
GenerationUtils.compileManyFilesGetGenerationStateForTest(jetCoreEnvironment.getProject(), files);
Disposer.dispose(getTestRootDisposable());
}