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