KCode.kt revision d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01
1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/*
2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project
3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License.
5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at
6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software
8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and
11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License.
12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */
13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
14fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.writer
15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
164ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport android.databinding.tool.util.StringUtils
17d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.BitSet
18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
19d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass KCode (private val s : String? = null){
20d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
21d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private var sameLine = false
22d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
234ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta    private val lineSeparator = StringUtils.LINE_SEPARATOR
24895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar
25d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    class Appendix(val glue : String, val code : KCode)
26d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private val nodes = arrayListOf<Any>()
28d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
29fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    companion object {
30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        private val cachedIndentations = BitSet()
31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        private val indentCache = arrayListOf<String>()
32d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        fun indent(n: Int): String {
33d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (cachedIndentations.get(n)) {
34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return indentCache.get(n)
35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val s = (0..n-1).fold(""){prev, next -> "${prev}    "}
37d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cachedIndentations.set(n, true )
3859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            while (indentCache.size <= n) {
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                indentCache.add("");
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            indentCache.set(n, s)
42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return s
43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun isNull(kcode : KCode?) = kcode == null || (kcode.nodes.isEmpty() && (kcode.s == null || kcode.s.trim() == ""))
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun tab(vararg codes : KCode?) : KCode {
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { tab(it) }
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun tab(codes : Collection<KCode?> ) : KCode {
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { tab(it) }
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
5859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    infix fun tab(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val c = KCode(s)
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (init != null) {
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            c.init()
62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return tab(c)
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
66d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    fun tab(c : KCode?) : KCode {
675d454e5f2397a3b160f081ce123b4ca7ff0fc356Yigit Boyar        if (c == null || isNull(c)) {
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return this
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nodes.add(c)
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun nls(vararg codes : KCode?) : KCode {
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { nl(it) }
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
78d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun nls(codes : Collection<KCode?>) : KCode {
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { nl(it) }
81d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
83d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
84d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun nl(c : KCode?) : KCode {
855d454e5f2397a3b160f081ce123b4ca7ff0fc356Yigit Boyar        if (c == null || isNull(c)) {
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return this
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nodes.add(c)
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        c!!.sameLine = true
90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun nl(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
94d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val c = KCode(s)
95d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (init != null) {
96d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            c.init()
97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return nl(c)
99d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
101d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun apps(glue : String = "", vararg codes : KCode?) : KCode {
102d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { app(glue, it)}
103d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun apps(glue : String = "", codes : Collection<KCode?>) : KCode {
107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { app(glue, it)}
108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun app(glue : String = "", c : KCode?) : KCode {
112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (isNull(c)) {
113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return this
114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nodes.add(Appendix(glue, c!!))
116d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
11959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    infix fun app(s : String) : KCode {
120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val c = KCode(s)
121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return app("", c)
122d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
123d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
124d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun app(glue : String = "", s : String?, init : (KCode.() -> Unit)? = null) : KCode {
125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val c = KCode(s)
126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (init != null) {
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            c.init()
128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return app(glue, c)
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
133d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun toS(n : Int, sb : StringBuilder) {
134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (s != null) {
135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            sb.append(s)
136d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val newlineFirstNode = s != null || (nodes.isNotEmpty() && nodes.first() is Appendix)
138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var addedChild = false
139d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nodes.forEach { when(it) {
140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            is Appendix -> {
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                sb.append(it.glue)
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                it.code.toS(n, sb)
143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            is KCode -> {
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val childTab = n + (if(it.sameLine) 0 else 1)
146d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (addedChild || newlineFirstNode) {
147895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    sb.append(lineSeparator)
148d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    sb.append("${indent(childTab)}")
149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
150d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                it.toS(childTab, sb)
151d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                addedChild = true
152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        } }
154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun generate() : String {
158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val sb = StringBuilder()
159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        toS(0, sb)
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return sb.toString()
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun kcode(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val c = KCode(s)
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if (init != null) {
167d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        c.init()
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return c
1704ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta}
171