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>) {
|
class AndroidUIXmlParser(val project: Project?, val searchPaths: Collection<File>) {
|
||||||
|
|
||||||
val ids: MutableCollection<AndroidID> = ArrayList()
|
val ids: MutableCollection<AndroidWidget> = ArrayList()
|
||||||
val kw = KotlinStringWriter()
|
val kw = KotlinStringWriter()
|
||||||
val androidImports = arrayListOf("android.app.Activity",
|
val androidImports = arrayListOf("android.app.Activity",
|
||||||
"android.view.View")
|
"android.view.View",
|
||||||
|
"android.widget.*")
|
||||||
|
|
||||||
public fun parse(): String {
|
public fun parse(): String {
|
||||||
doParse()
|
doParse()
|
||||||
@@ -53,19 +54,23 @@ class AndroidUIXmlParser(val project: Project?, val searchPaths: Collection<File
|
|||||||
val factory = SAXParserFactory.newInstance()
|
val factory = SAXParserFactory.newInstance()
|
||||||
factory?.setNamespaceAware(true)
|
factory?.setNamespaceAware(true)
|
||||||
val parser = factory!!.newSAXParser() // TODO: annotate this
|
val parser = factory!!.newSAXParser() // TODO: annotate this
|
||||||
val handler = AndroidXmlHandler({ id -> ids.add(AndroidID(id)) })
|
val handler = AndroidXmlHandler({ id, wClass -> widgetCallback(id, wClass) })
|
||||||
writeImports()
|
writeImports()
|
||||||
for (xmlStream in xmlStreams) {
|
for (xmlStream in xmlStreams) {
|
||||||
parser.parse(xmlStream, handler)
|
parser.parse(xmlStream, handler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun widgetCallback(id: String, className: String) {
|
||||||
|
ids.add(AndroidWidget(id, className))
|
||||||
|
}
|
||||||
|
|
||||||
private fun produceKotlinSignatures(): StringBuffer {
|
private fun produceKotlinSignatures(): StringBuffer {
|
||||||
for (id in ids) {
|
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",
|
kw.writeImmutableExtensionProperty(receiver = "Activity",
|
||||||
name = id.toString(),
|
name = id.id,
|
||||||
retType = "View",
|
retType = id.className,
|
||||||
getterBody = body )
|
getterBody = body )
|
||||||
}
|
}
|
||||||
return kw.output()
|
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 org.xml.sax.Attributes
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
|
||||||
class AndroidXmlHandler(val idCallback: (String)-> Unit): DefaultHandler() {
|
class AndroidXmlHandler(val elementCallback: (String, String)-> Unit): DefaultHandler() {
|
||||||
|
|
||||||
override fun startDocument() {
|
override fun startDocument() {
|
||||||
super<DefaultHandler>.startDocument()
|
super<DefaultHandler>.startDocument()
|
||||||
@@ -18,7 +18,8 @@ class AndroidXmlHandler(val idCallback: (String)-> Unit): DefaultHandler() {
|
|||||||
val hashMap = attributes.toMap()
|
val hashMap = attributes.toMap()
|
||||||
val s = hashMap["id"]
|
val s = hashMap["id"]
|
||||||
val idPrefix = "@+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) {
|
override fun endElement(uri: String?, localName: String, qName: String) {
|
||||||
|
|||||||
+28
-23
@@ -5,19 +5,21 @@ trait KotlinWriter
|
|||||||
class KotlinStringWriter : KotlinWriter {
|
class KotlinStringWriter : KotlinWriter {
|
||||||
|
|
||||||
val ctx = Context()
|
val ctx = Context()
|
||||||
|
val imports = ctx.fork()
|
||||||
|
val body = ctx.fork()
|
||||||
|
|
||||||
fun writeFunction(name: String,
|
fun writeFunction(name: String,
|
||||||
args: Collection<String>?,
|
args: Collection<String>?,
|
||||||
retType: String,
|
retType: String,
|
||||||
body: Collection<String>) {
|
stmts: Collection<String>) {
|
||||||
val returnTerm = if (retType == "" || retType == "Unit") "" else ": $retType"
|
val returnTerm = if (retType == "" || retType == "Unit") "" else ": $retType"
|
||||||
val argStr = if (args != null) args.join(", ") else ""
|
val argStr = if (args != null) args.join(", ") else ""
|
||||||
ctx.writeln("fun $name($argStr)$returnTerm {")
|
body.writeln("fun $name($argStr)$returnTerm {")
|
||||||
ctx.incIndent()
|
body.incIndent()
|
||||||
for (stmt in body)
|
for (stmt in stmts)
|
||||||
ctx.writeln(stmt)
|
body.writeln(stmt)
|
||||||
ctx.decIndent()
|
body.decIndent()
|
||||||
ctx.writeln("}")
|
body.writeln("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeExtensionFunction(receiver: String,
|
fun writeExtensionFunction(receiver: String,
|
||||||
@@ -31,24 +33,24 @@ class KotlinStringWriter : KotlinWriter {
|
|||||||
fun writeImmutableProperty(name: String,
|
fun writeImmutableProperty(name: String,
|
||||||
retType: String,
|
retType: String,
|
||||||
getterBody: Collection<String>) {
|
getterBody: Collection<String>) {
|
||||||
ctx.writeln("val $name: $retType")
|
body.writeln("val $name: $retType")
|
||||||
ctx.incIndent()
|
body.incIndent()
|
||||||
ctx.write("get() ")
|
body.write("get() ")
|
||||||
if (getterBody.size > 1) {
|
if (getterBody.size > 1) {
|
||||||
ctx.writeNoIndent("{\n")
|
body.writeNoIndent("{\n")
|
||||||
ctx.incIndent()
|
body.incIndent()
|
||||||
for (stmt in getterBody) {
|
for (stmt in getterBody) {
|
||||||
ctx.writeln(stmt)
|
body.writeln(stmt)
|
||||||
}
|
}
|
||||||
ctx.decIndent()
|
body.decIndent()
|
||||||
ctx.writeln("}")
|
body.writeln("}")
|
||||||
} else {
|
} else {
|
||||||
ctx.writeNoIndent("=")
|
body.writeNoIndent("=")
|
||||||
ctx.writeNoIndent(getterBody.join("").replace("return", ""))
|
body.writeNoIndent(getterBody.join("").replace("return", ""))
|
||||||
ctx.newLine()
|
body.newLine()
|
||||||
}
|
}
|
||||||
ctx.decIndent()
|
body.decIndent()
|
||||||
ctx.newLine()
|
body.newLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeImmutableExtensionProperty(receiver: String,
|
fun writeImmutableExtensionProperty(receiver: String,
|
||||||
@@ -59,13 +61,16 @@ class KotlinStringWriter : KotlinWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun writeImport(what: String) {
|
fun writeImport(what: String) {
|
||||||
ctx.writeln("import $what")
|
imports.writeln("import $what")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeEmptyLine() {
|
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.app.Activity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.*
|
||||||
|
|
||||||
val Activity.item_detail_container: View
|
val Activity.item_detail_container: FrameLayout
|
||||||
get() = findViewById(R.id.item_detail_container)!!
|
get() = findViewById(R.id.item_detail_container) as FrameLayout
|
||||||
|
|
||||||
val Activity.textView1: View
|
val Activity.textView1: TextView
|
||||||
get() = findViewById(R.id.textView1)!!
|
get() = findViewById(R.id.textView1) as TextView
|
||||||
|
|
||||||
val Activity.password: View
|
val Activity.password: EditText
|
||||||
get() = findViewById(R.id.password)!!
|
get() = findViewById(R.id.password) as EditText
|
||||||
|
|
||||||
val Activity.textView2: View
|
val Activity.login: Button
|
||||||
get() = findViewById(R.id.textView2)!!
|
get() = findViewById(R.id.login) as Button
|
||||||
|
|
||||||
val Activity.passwordConfirmation: View
|
|
||||||
get() = findViewById(R.id.passwordConfirmation)!!
|
|
||||||
|
|
||||||
val Activity.login: View
|
|
||||||
get() = findViewById(R.id.login)!!
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,22 +18,6 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ems="10"
|
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" />
|
android:inputType="textPassword" />
|
||||||
|
|
||||||
<Button
|
<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 {
|
public class AndroidXmlTest extends TestCaseWithTmpdir {
|
||||||
|
|
||||||
private final File singleFile = new File(getTestDataPath() + "/converter/singleFile/layout.xml");
|
private final File singleFile = new File(getTestDataPath() + "/converter/singleFile/layout.xml");
|
||||||
private final File fakeActivity = new File(getTestDataPath() + "/fakeHelpers/Activity.kt");
|
private final File fakeActivitySrc = new File(getTestDataPath() + "/fakeHelpers/Activity.kt");
|
||||||
private final File fakeView = new File(getTestDataPath() + "/fakeHelpers/View.kt");
|
private final File fakeViewSrc = new File(getTestDataPath() + "/fakeHelpers/View.kt");
|
||||||
|
private final File fakeWidgetsSrc = new File(getTestDataPath() + "/fakeHelpers/Widgets.kt");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
@@ -54,15 +55,17 @@ public class AndroidXmlTest extends TestCaseWithTmpdir {
|
|||||||
JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(getTestRootDisposable(),
|
JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(getTestRootDisposable(),
|
||||||
ConfigurationKind.ALL);
|
ConfigurationKind.ALL);
|
||||||
JetFile psiFile = JetTestUtils.createFile(singleFile.getName(), text, jetCoreEnvironment.getProject());
|
JetFile psiFile = JetTestUtils.createFile(singleFile.getName(), text, jetCoreEnvironment.getProject());
|
||||||
JetFile fakeActivityClass = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeActivity);
|
JetFile fakeActivity = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeActivitySrc);
|
||||||
JetFile fakeViewClass = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeView);
|
JetFile fakeView = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeViewSrc);
|
||||||
|
JetFile fakeWidgets = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(), fakeWidgetsSrc);
|
||||||
JetFile fakeRClass = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(),
|
JetFile fakeRClass = JetTestUtils.loadJetFile(jetCoreEnvironment.getProject(),
|
||||||
new File(getTestDataPath() + "/converter/singleFile/R.kt"));
|
new File(getTestDataPath() + "/converter/singleFile/R.kt"));
|
||||||
List<JetFile> files = new ArrayList<JetFile>();
|
List<JetFile> files = new ArrayList<JetFile>();
|
||||||
files.add(psiFile);
|
files.add(psiFile);
|
||||||
files.add(fakeActivityClass);
|
files.add(fakeActivity);
|
||||||
files.add(fakeViewClass);
|
files.add(fakeView);
|
||||||
files.add(fakeRClass);
|
files.add(fakeRClass);
|
||||||
|
files.add(fakeWidgets);
|
||||||
GenerationUtils.compileManyFilesGetGenerationStateForTest(jetCoreEnvironment.getProject(), files);
|
GenerationUtils.compileManyFilesGetGenerationStateForTest(jetCoreEnvironment.getProject(), files);
|
||||||
Disposer.dispose(getTestRootDisposable());
|
Disposer.dispose(getTestRootDisposable());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user