recompose is a tool for converting Android layouts in XML to Kotlin code using Jetpack Compose.

Overview

recompose

recompose is a tool for converting Android layouts in XML to Kotlin code using Jetpack Compose. It can be used on the command line, as IntelliJ / Android Studio plugin or as a library in custom code.

Running

IntelliJ / Android Studio plugin

The plugin does not get published yet. If you want to try them then you'll have to build them from code. Use the Gradle task runIde to run a test IDE with the plugin installed or create an installable plugin with the buildPlugin task. The plugin zip will be placed in recompose-idea/build/distributions/. To learn how to install it, read the Install plugin from disk section in the IntelliJ docs.

Command-line interface (CLI)

Like the plugin, the command-line interface does not get published yet. You can run it directly from Gradle via ./gradlew recompose-cli:run --args="list file paths..". Alternatively you can run the assembleDist which will place a zip/tar containing a binary into recompose-cli/build/distributions/.

Usage: recompose [OPTIONS] INPUT...

Options:
  -o, --output PATH  Output directory for Kotlin code
  -h, --help         Show this message and exit

Arguments:
  INPUT  Layout XML files to convert to Kotlin

Building

Either import the project into IntelliJ IDEA or use Gradle on the command line (via the provided gradlew wrapper).

Modules

  • recompose-ast: Contains the data classes for the Abstract Syntax Tree (AST) representing a parsed XML layout.
  • recompose-cli: A command-line interface (CLI) for running recompose in a shell.
  • recompose-composer: Responsible for taking an AST and transforming it into the equivalent Composable Kotlin code.
  • recompose-idea: An IntelliJ IDEA / Android Studio plugin that allows copying XML layouts and pasting as Composable Kotlin code.
  • recompose-test: Contains test data and helpers for unit tests.

Important gradle tasks

  • clean: Deletes the build directories.
  • test: Runs all unit tests in all modules.
  • runIde: Runs IntelliJ IDEA with the plugin installed.
  • buildPlugin: Builds the IntelliJ / Android Studio plugin and makes it available in recompose-idea/build/distributions.

How does this work?

The Parser (recompose-parser) takes the input XML and transforms it into an Abstract Syntax Tree (recompose-ast). The Composer (recompose-composer) takes the AST and translates it into Kotlin code calling Composables.

The IntelliJ / Android Studio plugin (recompose-idea) uses that to perform the translation when pasting copied XML code. And the CLI (recompose-cli) uses it to translate files.

Can I contribute?

Yes, absolutely. There are a ton of Views and attributes to support. The list of issues labeled with good first issue are a good place to start. An issue from the list labeled with help wanted may be a good follow-up. Just comment on any issue that interests you.

License

Copyright 2020 Sebastian Kaspari

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.
Comments
  • TextView: Add support for android:maxLines

    TextView: Add support for android:maxLines

    android:maxLines Makes the TextView be at most this many lines tall. When used on an editable text, the inputType attribute's value must be combined with the textMultiLine flag for the maxLines attribute to apply.

    XML attribute: https://developer.android.com/reference/android/widget/TextView?hl=en#attr_android:maxLines

    Jetpack Compose:

    Text(
       ...
       maxLines = Int = Int.MAX_VALUE
       ...
    )
    

    We are parsing TextView here: https://github.com/pocmo/recompose/blob/main/recompose-parser/src/main/kotlin/recompose/parser/xml/view/TextView.kt

    And create a TextViewNode from it: https://github.com/pocmo/recompose/blob/main/recompose-ast/src/main/kotlin/recompose/ast/view/TextViewNode.kt

    And we turn the node into Kotlin code here: https://github.com/pocmo/recompose/blob/main/recompose-composer/src/main/kotlin/recompose/composer/visitor/ComposingVisitor.kt#L82-L94

    To solve this issue:

    • Parse the attribute and add the value to TextViewNode. Probably a nullable Int? is needed.
    • Add it to the list of parameters in ComposingVisitor.
    • Add a test case to ParserTest and ComposerTest.
    enhancement good first issue 
    opened by pocmo 5
  • Map 0dp width/height in ConstraintLayout to fillMaxWidth()/fillMaxHeight()

    Map 0dp width/height in ConstraintLayout to fillMaxWidth()/fillMaxHeight()

    Using ConstraintLayout you'd often set android:layout_width or android:layout_height of a View to 0dp to let the ConstraintLayout stretch it based on the constraints. ConstraintLayout() doesn't behave that way if you add a width(0.dp) modifier. In that case we need to translate it to fillMaxWidth() or fillMaxHeight().

    For now we could just always translate 0dp to fillMaxWidth() or fillMaxHeight() if the node has any constraint set.

    enhancement 
    opened by pocmo 3
  • Refactored AST and Parser to be more extensible and structured.

    Refactored AST and Parser to be more extensible and structured.

    Introduced an API to for defining how an Attribute and a View Element can be parsed from XML to AST. This API has two Key interfaces, AttributeTransformer to define how an XML-Attribute is converted and Node Transformer to define how an entire XML-Element in is transformed. A Node Transformer can contain multiple AttributeTransformer, and will be automatically picked up by the NodeMatcher class, that scans the classpath for classes implementing the NodeTransformer interface and uses them to match a node name on a fitting NodeTransformer. The generated AST from that can be consumed by any class implementing the Visitor interface.

    This work is just the first step for future optimizations. I am planning to enhance the AST to be able to apply an optimiser that can eliminate some nodes on the attributes (e.g. you can eliminate fillMaxHeight and fillMaxWidth and replace it with fillParent if both are present).

    opened by Ditscheridou 2
  • Issue #65 Add

    Issue #65 Add "Don't show this dialog next time" checkbox

    This adds a "Don't show this dialog next time" checkbox that applies for the current project. I can easily switch it if you prefer the setting to apply to the current workspace instead.

    To clear the setting, you can remove it from .idea/workspace.xml in the current project.

    opened by colintheshots 2
  • Issue #91: Add support for ImageButton

    Issue #91: Add support for ImageButton

    I added this check to the LineWriter:

    fun startLine(text: String = "") {
            if (builder.isNotEmpty() && checkLast('(').not()) {
                repeat(indent) { builder.append(INDENT) }
            }
            builder.append(text)
    }
    

    Where checkLast is

    fun checkLast(char: Char): Boolean {
            return builder.last() == char
    }
    

    Because without the check instead of having as desired:

    Button(onClick = {}, modifier = Modifier.width(100.dp).height(100.dp)) {
             Image(imageResource(R.drawable.ic_lock_power_off))
    }
    

    I get:

    Button(onClick = {}, modifier = Modifier.width(100.dp).height(100.dp)) {
             Image(      imageResource(R.drawable.ic_lock_power_off))
    }
    
    opened by t-regbs 1
  • Add

    Add "Don't show this dialog next time" checkbox to plugin prompt

    #7, #59 added a confirmation dialog to the plugin, before pasting code. Like the Kotlin plugin we should offer a "Don't show this dialog next time" option.

    enhancement help wanted plugin 
    opened by pocmo 1
  • Add Confirmation Dialog, check if target file is Kotlin, use runWrite…

    Add Confirmation Dialog, check if target file is Kotlin, use runWrite…

    Hi @pocmo , i've implemented: Check paste destination #6 Wrap code inserting Kotlin code in runWriteAction() #51 And Show a confirmation dialog before pasting #7

    But i'm having two issues:

    1. I can't figure out how to extract the strings from the confirmation dialog into a resource bundle. I know i can set " messages.MyPluginBundle" in the plugin.xml, but i cant use the keys in the code 🤷

    2. The confirmation dialog has a "Don't show this dialog next time"-Checkbox. Right now, it does nothing. I can implement that the setting will be saved, but i think we would also need a page in the IntelliJ settings to reset this option. Just wanted to make sure, if this is wanted, before i implement it.

    opened by Foso 1
  • #98 Add support for style attribute

    #98 Add support for style attribute

    Issue: https://github.com/pocmo/recompose/issues/98 Add support for style attribute

    Context

    The plugin cannot handle a layout with a style attribute (like ?selectableItemBackground)

    Changes

    Convert attributes like ?selectableItemBackground in imageAttribute(selectableItemBackground)

    opened by omarmiatello 0
  • #96 Add support for MaterialCardView

    #96 Add support for MaterialCardView

    Issue: https://github.com/pocmo/recompose/issues/96 Add support for MaterialCardView

    Context

    com.google.android.material.card.MaterialCardView extends androidx.cardview.widget.CardView and could use the same parser.

    View available in:

    com.google.android.material:material:1.2.1
    

    Changes

    CardView and MaterialCardView use the same parser: cardView()

    internal fun XmlPullParser.node(): Node {
        require(START_TAG, null, null)
    
        return when (name) {
    
    		// ...
    
            "androidx.cardview.widget.CardView",  
            "com.google.android.material.card.MaterialCardView" -> cardView()
    
    		// ...
         }
    }
    
    
    opened by omarmiatello 0
  • Add support for MaterialCardView

    Add support for MaterialCardView

    com.google.android.material.card.MaterialCardView extends androidx.cardview.widget.CardView and could use the same parser.

    View available in:

    com.google.android.material:material:1.2.1
    
    enhancement 
    opened by omarmiatello 0
  • Newer Android Studio not supported?

    Newer Android Studio not supported?

    Plugin 'Recompose' (version '1.0') is not compatible with the current version of the IDE, because it requires build 202.* or older but the current build is AI-211.7628.21
    
    plugin build 
    opened by wu-coding 3
  • An illegal reflective access operation has occurred

    An illegal reflective access operation has occurred

    gradle buildPlugin

    WARNING: An illegal reflective access operation has occurred
    WARNING: Illegal reflective access by com.intellij.ide.IdeEventQueue to constructor sun.awt.PostEventQueue(java.awt.EventQueue)
    WARNING: Please consider reporting this to the maintainers of com.intellij.ide.IdeEventQueue
    WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
    WARNING: All illegal access operations will be denied in a future release
    

    Android Studio Arctic Fox | 2020.3.1 Build #AI-203.7717.56.2031.7583922, built on July 26, 2021 Runtime version: 11.0.10+0-b96-7249189 amd64

    opened by Psijic 0
  • recompose.parser.Parser$ParserException: Unknown drawable format: @color/white

    recompose.parser.Parser$ParserException: Unknown drawable format: @color/white

    Hi, tnx for plugin, is it possible to fix this error:

    recompose.parser.Parser$ParserException: Unknown size value: @dimen/common_margin at recompose.parser.values.SizeKt.size(Size.kt:31) at recompose.parser.values.PaddingKt.padding(Padding.kt:29) at recompose.parser.xml.ViewKt.viewAttributes(View.kt:82) at recompose.parser.xml.viewgroup.LinearLayoutKt.linearLayout(LinearLayout.kt:33) at recompose.parser.xml.ViewKt.node(View.kt:51) at recompose.parser.xml.ViewGroupKt.viewGroupAttributes(ViewGroup.kt:37) at recompose.parser.xml.viewgroup.UnknownKt.unknown(Unknown.kt:31) at recompose.parser.xml.ViewKt.node(View.kt:69) at recompose.parser.xml.ViewGroupKt.viewGroupAttributes(ViewGroup.kt:37) at recompose.parser.xml.viewgroup.ConstraintLayoutKt.constraintLayout(ConstraintLayout.kt:32) at recompose.parser.xml.ViewKt.node(View.kt:65) at recompose.parser.xml.ViewGroupKt.viewGroupAttributes(ViewGroup.kt:37) at recompose.parser.xml.viewgroup.UnknownKt.unknown(Unknown.kt:31) at recompose.parser.xml.ViewKt.node(View.kt:69) at recompose.parser.xml.LayoutKt.layout(Layout.kt:37) at recompose.parser.Parser.parse(Parser.kt:62) at recompose.parser.Parser.parse(Parser.kt:53) at recompose.parser.Parser.parse(Parser.kt:37)

    bug enhancement 
    opened by e-tverdokhleb 1
  • Edittext seems to close the parent tag

    Edittext seems to close the parent tag

    The parser seems to close a parent tag for EditText.

    FrameLayout {
        EditText()
        View()
    }
    

    Will result in:

    FrameLayout {
        EditText()
    }
    View()
    

    Same occurs with LinearLayout.

    bug 
    opened by tieskedh 1
Owner
Sebastian Kaspari
#Android #developer living in #Passau. Developer of #Yaaic. Working on #Firefox / #Focus / #Components / X for Android @mozilla.
Sebastian Kaspari
Map strings from csv to xml file

CsvToXmlMapper While translating your app, your translator provides you with a .csv file containing the translated strings and you wonder how boring a

Abhriya Roy 6 Sep 25, 2021
KDoctor - A command-line tool that helps to set up the environment for Kotlin Multiplatform Mobile app development

KDoctor is a command-line tool that helps to set up the environment for Kotlin Multiplatform Mobile app development.

Kotlin 331 Dec 29, 2022
Tool to look for several security related Android application vulnerabilities

Quick Android Review Kit This tool is designed to look for several security related Android application vulnerabilities, either in source code or pack

LinkedIn 2.9k Jan 2, 2023
A tool to validate text inside TextInputLayout

Download dependencies { implementation 'com.github.anderscheow:validator:2.2.1' } Usage Available rules LengthRule MaxRule MinRule NotEmptyRule NotN

Anders Cheow 129 Nov 25, 2022
An easy-to-use, cross-platform measurement tool that pulls data out of CD pipelines and analysis the four key metrics for you.

Maintained by SEA team, ThoughtWorks Inc. Read this in other languages: English, 简体中文 Table of Contents About the Project Usage How to Compute Contrib

Thoughtworks 277 Jan 7, 2023
An intelligent diff tool for the output of Gradle's dependencies task

Dependency Tree Diff An intelligent diff tool for the output of Gradle's dependencies task which always shows the path to the root dependency. +--- c

Jake Wharton 693 Dec 26, 2022
Utility tool to make you a computer ninja.

Cmd Window Never spend 6 minutes doing something by hand when you can spend 6 hours failing to automate it - Zhuowej Zhang What is this about? This to

Marcin Radoszewski 3 Feb 1, 2022
BinGait is a tool to disassemble and view java class files, developed by BinClub.

BinGait Tool to diassemble java class files created by x4e. Usage To run BinGait, run java -jar target/bingait-shadow.jar and BinGait will launch. If

null 18 Jul 7, 2022
A command line tool for NFT stuff

MartaKli is a command line tool to help you generate your NFT pfp project. Current features: Generate batch of images using different layers and corre

Martabak Cult 2 Oct 4, 2022
Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platform the code is running.

Trail Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platfor

Mauricio Togneri 13 Aug 29, 2022
λRPC allows using code with high-order functions as a service

λRPC Simple native RPC with high order functions support. Inspired by @altavir and Communicator. λRPC allows using code with high-order functions as a

Andrey Stoyan 5 May 18, 2022
CreditCardHelper 🖊️ A Jetpack-Compose library providing useful credit card utilities such as card type recognition and TextField ViewTransformations

CreditCardHelper ??️ A Jetpack-Compose library providing useful credit card utilities such as card type recognition and TextField ViewTransformations

Stelios Papamichail 18 Dec 19, 2022
Generate helper methods for compose navigation using KSP

Compose NavGen Generate helper methods for compose navigation using KSP. ?? You can try it now, but it's still under development. ?? TODO Support defa

Kenji Abe 6 Feb 5, 2022
iTunes 11-style color matching code for Android

##About ColorArt is a library that uses an image to create a themed image/text display. It's a port of the idea found on the Panic Blog to work on And

Michael Evans 896 Jan 8, 2023
SoLoader is a native code loader for Android.

SoLoader is a native code loader for Android. It takes care of unpacking your native libraries and recursively loads dependencies on platforms that don't support that out of the box.

Meta 1.2k Jan 3, 2023
Runtime code generation for the Java virtual machine.

Byte Buddy runtime code generation for the Java virtual machine Byte Buddy is a code generation and manipulation library for creating and modifying Ja

Rafael Winterhalter 5.3k Jan 7, 2023
A small library which will save you from writing the same intent creation code again and again for the most simple tasks

Android Intents A small library which will save you from writing the same intent creation code again and again for the most simple tasks. I found myse

MarvinLabs 420 Nov 20, 2022
Polytech computer graphics couerse code scam script

Js-code-parser Polytech computer graphics couerse code scam script Копируйте строку скрипта с дебаггера с странички лабы. Вставляйте в файлик test.txt

Daniil Bakin 2 Dec 18, 2022
A Telegram bot utilities that help to reduce the code amount

Flume Party A Telegram bot utilities that help to reduce code amount. Real project examples Pull Party Bot: 19% of code has been reduced. Resistance B

pool party 1 Jun 8, 2022