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:
committed by
Yan Zhulanow
parent
31dc8194f1
commit
aa01d6d7cf
+11
-6
@@ -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
|
||||
|
||||
+3
-2
@@ -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) {
|
||||
|
||||
+28
-23
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user