1 24 25 package org.aspectj.compiler.base; 26 import org.aspectj.compiler.base.ast.*; 27 28 import java.util.*; 29 import java.io.*; 30 31 import org.aspectj.tools.ide.SourceLine; 32 import org.aspectj.util.CollectionUtil; 33 34 public class CodeWriter extends CompilerObject { 35 private boolean writeComments = false; 36 private LineMap lineMap = null; 37 private CodeText out; 38 40 public CodeWriter(JavaCompiler compiler) { 41 this(compiler, 1024, null); 42 } 43 44 public CodeWriter(JavaCompiler compiler, int expectedSize, LineMap lineMap) { 45 super(compiler); 46 out = new CodeText(expectedSize); 47 this.lineMap = lineMap; 48 this.writeComments = !compiler.getOptions().nocomments; 50 } 51 52 public String getString() { 53 return out.getString(); 54 } 55 56 public void writeTo(OutputStream ostream) throws IOException { 57 out.writeTo(ostream); 58 } 59 60 private boolean onlySignatures = false; 61 public boolean isOnlySignatures() { return onlySignatures; } 62 public void setOnlySignatures(boolean v) { onlySignatures = v; } 63 64 private boolean onlyPatch = false; 65 public boolean isOnlyPatch() { return onlyPatch; } 66 public void setOnlyPatch(boolean v) { onlyPatch = v; } 67 68 public void parenExpr(Expr expr) { 69 openParen('('); 70 write(expr); 71 closeParen(')'); 72 } 73 74 public void parenExprs(Exprs exprs) { 75 openParen('('); 76 write(exprs); 77 closeParen(')'); 78 } 79 80 public void writeChildren(ASTObject parent) { 81 if (parent == null) return; 82 final int N = parent.getChildCount(); 83 if (N > 0) write(parent.getChildAt(0)); 84 85 for(int i=1; i<N; i++) { 86 write(parent.getChildAt(i)); 87 } 88 } 89 90 public void writeChildrenWithCommas(ASTObject parent) { 91 if (parent == null) return; 92 final int N = parent.getChildCount(); 93 if (N > 0) write(parent.getChildAt(0)); 94 95 for(int i=1; i<N; i++) { 96 comma(); 97 write(parent.getChildAt(i)); 98 } 99 } 100 101 102 public void write(ASTObject node) { 103 try { 104 if (node == null) return; 105 106 if (writeComments) { 107 Comment comment = node.getComment(); 108 while (comment != null) { 109 comment.unparse(this); 110 comment = comment.getNextComment(); 111 } 112 } 113 114 if (lineMap != null) { 116 lineMap.noteNode(node); 117 } 118 119 node.unparse(this); 120 } catch (IOException ioe) { 121 } 123 } 124 125 public int getIndentSize() { return 2; } 126 127 private int lineStart = 0; 128 private int lastGoodBreak = -1; 129 private int lastPossibleBreak = -1; 130 131 public void noteGoodBreak() { 132 breakTooLongLine(); 133 lastGoodBreak = out.getIndex(); 134 } 135 136 public void notePossibleBreak() { 137 breakTooLongLine(); 138 lastPossibleBreak = out.getIndex(); 139 } 140 141 public void breakTooLongLine() { 142 int column = out.getIndex() - lineStart; 143 if (column < MAX_COLUMNS) return; 145 146 149 int breakPoint = -1; 150 if (lastGoodBreak != -1) { 151 breakPoint = lastGoodBreak; 152 } else if (lastPossibleBreak != -1) { 153 breakPoint = lastPossibleBreak; 154 } else { 155 return; 157 } 158 159 insertNewLine(breakPoint); 160 } 161 162 public void insertNewLine(int breakAtIndex) { 163 byte[] saveData = out.backup(breakAtIndex); 164 out.write(newLine); 166 lineStart = out.getIndex(); 167 lastPossibleBreak = lastGoodBreak = -1; 168 writeSpaces(indents + 4); 169 out.write(saveData); 170 lastPossibleBreak = out.getIndex(); 171 } 172 173 174 175 public void comma() { 176 write(','); 177 optionalSpace(); 178 noteGoodBreak(); 179 } 180 181 public void requiredSpace() { 182 out.write(' '); 184 notePossibleBreak(); 185 } 186 public void optionalSpace() { 187 out.write(' '); 189 notePossibleBreak(); 190 } 191 192 public void writeKeyword(String keyword) { 193 write(keyword); 194 } 195 196 public void writeOp(String op) { 197 optionalSpace(); 198 write(op); 199 optionalSpace(); 200 } 201 202 final int MAX_PAREN_DEPTH = 32; 205 private int[] parenPositions = new int[MAX_PAREN_DEPTH+1]; 206 private int parenDepth = 0; 207 208 public void openParen(char paren) { 209 write(paren); 210 parenDepth++; 211 parenPositions[parenDepth > MAX_PAREN_DEPTH ? MAX_PAREN_DEPTH : parenDepth] = out.getIndex(); 212 notePossibleBreak(); 213 } 214 215 public void closeParen(char paren) { 216 write(paren); 217 parenDepth--; 218 } 219 220 221 public void closeStmt() { 222 write(';'); 223 } 225 226 227 private int indents=0; 228 public int getIndents() { 229 return indents; 230 } 231 public void setIndents(int indents) { 232 this.indents = indents; 233 } 234 235 public void openBlock() { 236 writeln("{"); 238 indent(); 239 } 240 241 public void closeBlock() { 242 dedent(); 243 write("} "); 244 } 245 246 public void indent() { 247 indents += getIndentSize(); 248 } 249 250 public void dedent() { 251 indents -= getIndentSize(); 252 } 253 254 public void writeLines(String text) { 256 if (text == null) return; 257 258 int currentPos = 0; 260 while (true) { 261 int newlinePos = text.indexOf('\n', currentPos); 262 if (newlinePos == -1) break; 263 writeln(text.substring(currentPos, newlinePos)); 264 currentPos = newlinePos + 1; 265 } 266 267 write(text.substring(currentPos)); 268 } 269 270 271 public void write(String text) { 274 doIndent(); 275 out.write(text); 276 } 278 279 public void write(char ch) { 280 doIndent(); 281 out.write(ch); 282 } 284 285 public void writeln(String text) { 287 write(text); 288 newLine(); 289 } 290 291 final String newLine = "\n"; 293 294 final int COMMENT_COLUMN = 67; 295 final int MAX_COLUMNS = 100; 296 public void newLine() { 297 breakTooLongLine(); 299 300 if (writeComments && lineMap != null && lineMap.hasCurrentSourceLine()) { 301 int column = out.getIndex() - lineStart; 302 if (column < COMMENT_COLUMN) { 303 writeSpaces(COMMENT_COLUMN - column); 304 } else { 305 out.write(' '); 306 } 307 308 out.write("//"); 309 out.write(new File(lineMap.getCurrentSourceFile()).getName()); 312 out.write(":" + lineMap.getCurrentSourceLine()); 313 } 314 out.write(newLine); 315 if (lineMap != null) { 316 lineMap.noteNewLine(); 317 } 318 lineStart = out.getIndex(); 319 needIndent = true; 320 lastGoodBreak = -1; 321 lastPossibleBreak = -1; 322 } 323 324 private boolean needIndent = false; 325 void doIndent() { 326 if (!needIndent) return; 327 needIndent = false; 328 writeSpaces(indents); 329 } 330 331 final void writeSpaces(final int N) { 333 for (int i = 0; i < N; i++) { 335 out.write(' '); 336 } 337 } 338 339 public static final String HEADER_START = 340 "/* Generated by AspectJ version "; 341 342 public static boolean isGeneratedSource(File file) { 343 try { 344 Reader reader = new FileReader(file); 345 for(int i=0; i<HEADER_START.length(); i++) { 346 int ch = reader.read(); 347 if (ch != HEADER_START.charAt(i)) return false; 348 } 349 reader.close(); 350 return true; 351 } catch (IOException ioe) { 352 return false; 354 } 355 } 356 357 358 public void writeHeader() { 359 writeln(HEADER_START+Options.version+" */"); 360 } 361 } 362 363 364 class CodeText { 365 protected byte[] data; 366 protected int index; 367 protected boolean addSlash; 368 369 public CodeText(int expectedSize) { 370 data = new byte[expectedSize]; 371 index = 0; 372 addSlash = false; 373 } 374 375 public int getIndex() { 376 return index; 377 } 378 379 public byte[] backup(int toIndex) { 380 int backupSize = index - toIndex; 381 byte[] ret = new byte[backupSize]; 382 383 System.arraycopy(data, toIndex, ret, 0, backupSize); 384 385 index = toIndex; 386 return ret; 387 } 388 389 private final void expandTo(int newSize) { 390 if (newSize < data.length) return; 391 392 int newLength = data.length * 2; 393 while (newLength < newSize) newLength *= 2; 394 395 byte[] newData = new byte[newLength]; 396 System.arraycopy(data, 0, newData, 0, index); 397 data = newData; 398 } 399 400 401 public void write(byte b) { 402 expandTo(index + 1); 403 data[index++] = b; 404 } 405 406 public void write(byte[] bytes) { 407 expandTo(index + bytes.length); 408 System.arraycopy(bytes, 0, data, index, bytes.length); 409 index += bytes.length; 410 } 411 412 public void write(String s) { 413 final int N = s.length(); 414 for (int i = 0; i < N; i++) { 415 write(s.charAt(i)); 416 } 417 } 418 419 public void write(int ch) { 420 expandTo(index + 7); 421 422 if (addSlash && ch == 'u') { 423 data[index++] = (byte)'\\'; 424 } 426 427 if (ch == '\\') { 428 addSlash = !addSlash; 429 } else { 430 addSlash = false; 431 } 432 433 if (ch < 1 || ch > 126) { 434 int b1 = ch>>12; 435 int b2 = ch>>8 & 0xf; 436 int b3 = ch>>4 & 0xf; 437 int b4 = ch & 0xf; 438 439 data[index++] = (byte)'\\'; 440 data[index++] = (byte)'u'; 441 data[index++] = (byte)Character.forDigit(b1, 16); 442 data[index++] = (byte)Character.forDigit(b2, 16); 443 data[index++] = (byte)Character.forDigit(b3, 16); 444 data[index++] = (byte)Character.forDigit(b4, 16); 445 } else { 446 data[index++] = (byte)ch; 447 } 448 } 449 450 public String getString() { 451 try { 452 return new String (data, 0, index, "US-ASCII"); 453 } catch (UnsupportedEncodingException e) { 454 return new String (data, 0, index); 455 } 456 } 457 458 public void writeTo(OutputStream ostream) throws IOException { 459 ostream.write(data, 0, index); 460 ostream.flush(); 461 } 462 } 463 | Popular Tags |