KCode.kt revision 5d454e5f2397a3b160f081ce123b4ca7ff0fc356
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
16d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.BitSet
17d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass KCode (private val s : String? = null){
19d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
20d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private var sameLine = false
21d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
22895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar    private val lineSeparator = System.getProperty("line.separator")
23895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar
24d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    class Appendix(val glue : String, val code : KCode)
25d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
26d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private val nodes = arrayListOf<Any>()
27d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
28fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    companion object {
29d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        private val cachedIndentations = BitSet()
30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        private val indentCache = arrayListOf<String>()
31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        fun indent(n: Int): String {
32d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (cachedIndentations.get(n)) {
33d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return indentCache.get(n)
34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val s = (0..n-1).fold(""){prev, next -> "${prev}    "}
36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cachedIndentations.set(n, true )
37d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            while (indentCache.size() <= n) {
38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                indentCache.add("");
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            indentCache.set(n, s)
41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return s
42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun isNull(kcode : KCode?) = kcode == null || (kcode.nodes.isEmpty() && (kcode.s == null || kcode.s.trim() == ""))
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun tab(vararg codes : KCode?) : KCode {
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { tab(it) }
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun tab(codes : Collection<KCode?> ) : KCode {
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { tab(it) }
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun tab(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val c = KCode(s)
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (init != null) {
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            c.init()
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return tab(c)
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private fun tab(c : KCode?) : KCode {
665d454e5f2397a3b160f081ce123b4ca7ff0fc356Yigit Boyar        if (c == null || isNull(c)) {
67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return this
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nodes.add(c)
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun nls(vararg codes : KCode?) : KCode {
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { nl(it) }
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
78d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun nls(codes : Collection<KCode?>) : KCode {
79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { nl(it) }
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
81d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
83d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun nl(c : KCode?) : KCode {
845d454e5f2397a3b160f081ce123b4ca7ff0fc356Yigit Boyar        if (c == null || isNull(c)) {
85d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return this
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nodes.add(c)
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        c!!.sameLine = true
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun nl(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val c = KCode(s)
94d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (init != null) {
95d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            c.init()
96d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return nl(c)
98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
99d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun apps(glue : String = "", vararg codes : KCode?) : KCode {
101d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { app(glue, it)}
102d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
103d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun apps(glue : String = "", codes : Collection<KCode?>) : KCode {
106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        codes.forEach { app(glue, it)}
107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun app(glue : String = "", c : KCode?) : KCode {
111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (isNull(c)) {
112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return this
113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nodes.add(Appendix(glue, c!!))
115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return this
116d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun app(s : String) : KCode {
119d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val c = KCode(s)
120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return app("", c)
121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
122d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
123d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun app(glue : String = "", s : String?, init : (KCode.() -> Unit)? = null) : KCode {
124d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val c = KCode(s)
125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (init != null) {
126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            c.init()
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return app(glue, c)
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun toS(n : Int, sb : StringBuilder) {
133d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (s != null) {
134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            sb.append(s)
135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
136d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val newlineFirstNode = s != null || (nodes.isNotEmpty() && nodes.first() is Appendix)
137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var addedChild = false
138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nodes.forEach { when(it) {
139d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            is Appendix -> {
140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                sb.append(it.glue)
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                it.code.toS(n, sb)
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            is KCode -> {
144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val childTab = n + (if(it.sameLine) 0 else 1)
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (addedChild || newlineFirstNode) {
146895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    sb.append(lineSeparator)
147d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    sb.append("${indent(childTab)}")
148d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                it.toS(childTab, sb)
150d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                addedChild = true
151d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        } }
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun generate() : String {
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val sb = StringBuilder()
158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        toS(0, sb)
159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return sb.toString()
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun kcode(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val c = KCode(s)
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if (init != null) {
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        c.init()
167d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return c
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}