KCode.kt revision d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01
1/* 2 * 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 14package android.databinding.tool.writer 15 16import android.databinding.tool.util.StringUtils 17import java.util.BitSet 18 19class 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.get(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 fun tab(vararg codes : KCode?) : KCode { 49 codes.forEach { tab(it) } 50 return this 51 } 52 53 fun tab(codes : Collection<KCode?> ) : KCode { 54 codes.forEach { tab(it) } 55 return this 56 } 57 58 infix 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 fun nls(vararg codes : KCode?) : KCode { 75 codes.forEach { nl(it) } 76 return this 77 } 78 79 fun nls(codes : Collection<KCode?>) : KCode { 80 codes.forEach { nl(it) } 81 return this 82 } 83 84 fun nl(c : KCode?) : KCode { 85 if (c == null || isNull(c)) { 86 return this 87 } 88 nodes.add(c) 89 c!!.sameLine = true 90 return this 91 } 92 93 fun nl(s : String?, init : (KCode.() -> Unit)? = null) : KCode { 94 val c = KCode(s) 95 if (init != null) { 96 c.init() 97 } 98 return nl(c) 99 } 100 101 fun apps(glue : String = "", vararg codes : KCode?) : KCode { 102 codes.forEach { app(glue, it)} 103 return this 104 } 105 106 fun apps(glue : String = "", codes : Collection<KCode?>) : KCode { 107 codes.forEach { app(glue, it)} 108 return this 109 } 110 111 fun app(glue : String = "", c : KCode?) : KCode { 112 if (isNull(c)) { 113 return this 114 } 115 nodes.add(Appendix(glue, c!!)) 116 return this 117 } 118 119 infix fun app(s : String) : KCode { 120 val c = KCode(s) 121 return app("", c) 122 } 123 124 fun app(glue : String = "", s : String?, init : (KCode.() -> Unit)? = null) : KCode { 125 val c = KCode(s) 126 if (init != null) { 127 c.init() 128 } 129 return app(glue, c) 130 } 131 132 133 fun toS(n : Int, sb : StringBuilder) { 134 if (s != null) { 135 sb.append(s) 136 } 137 val newlineFirstNode = s != null || (nodes.isNotEmpty() && nodes.first() is Appendix) 138 var addedChild = false 139 nodes.forEach { when(it) { 140 is Appendix -> { 141 sb.append(it.glue) 142 it.code.toS(n, sb) 143 } 144 is KCode -> { 145 val childTab = n + (if(it.sameLine) 0 else 1) 146 if (addedChild || newlineFirstNode) { 147 sb.append(lineSeparator) 148 sb.append("${indent(childTab)}") 149 } 150 it.toS(childTab, sb) 151 addedChild = true 152 } 153 } } 154 155 } 156 157 fun generate() : String { 158 val sb = StringBuilder() 159 toS(0, sb) 160 return sb.toString() 161 } 162} 163 164fun kcode(s : String?, init : (KCode.() -> Unit)? = null) : KCode { 165 val c = KCode(s) 166 if (init != null) { 167 c.init() 168 } 169 return c 170} 171