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