OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 const int _LF = 0x0A; |
| 6 const int _CR = 0x0D; |
| 7 const int _LBRACE = 0x7B; |
| 8 |
| 9 class Annotation { |
| 10 /// 1-based line number of the annotation. |
| 11 final int lineNo; |
| 12 |
| 13 /// 1-based column number of the annotation. |
| 14 final int columnNo; |
| 15 |
| 16 /// 0-based character offset of the annotation within the source text. |
| 17 final int offset; |
| 18 |
| 19 /// The text in the annotation. |
| 20 final String text; |
| 21 |
| 22 Annotation(this.lineNo, this.columnNo, this.offset, this.text); |
| 23 } |
| 24 |
| 25 /// A source code text with annotated positions. |
| 26 /// |
| 27 /// An [AnnotatedCode] can be created from a [String] of source code where |
| 28 /// annotated positions are embedded using the syntax `@{text}`. For instance |
| 29 /// |
| 30 /// main() { |
| 31 /// @{foo-call}foo(); |
| 32 /// bar@{bar-args}(); |
| 33 /// } |
| 34 /// |
| 35 /// the position of `foo` call will hold an annotation with text 'foo-call' and |
| 36 /// the position of `bar` arguments will hold an annotation with text |
| 37 /// 'bar-args'. |
| 38 /// |
| 39 /// Annotation text cannot span multiple lines and cannot contain '}'. |
| 40 class AnnotatedCode { |
| 41 /// The source code without annotations. |
| 42 final String sourceCode; |
| 43 |
| 44 /// The annotations for the source code. |
| 45 final List<Annotation> annotations; |
| 46 |
| 47 AnnotatedCode.internal(this.sourceCode, this.annotations); |
| 48 |
| 49 /// Creates an [AnnotatedCode] by processing [annotatedCode]. Annotation of |
| 50 /// the form `@{...}` are converted into [Annotation]s and removed from the |
| 51 /// [annotatedCode] to process the source code. |
| 52 factory AnnotatedCode(String annotatedCode) { |
| 53 StringBuffer codeBuffer = new StringBuffer(); |
| 54 List<Annotation> annotations = <Annotation>[]; |
| 55 int index = 0; |
| 56 int offset = 0; |
| 57 int lineNo = 1; |
| 58 int columnNo = 1; |
| 59 while (index < annotatedCode.length) { |
| 60 int charCode = annotatedCode.codeUnitAt(index); |
| 61 switch (charCode) { |
| 62 case _LF: |
| 63 codeBuffer.write('\n'); |
| 64 offset++; |
| 65 lineNo++; |
| 66 columnNo = 1; |
| 67 break; |
| 68 case _CR: |
| 69 if (index + 1 < annotatedCode.length && |
| 70 annotatedCode.codeUnitAt(index + 1) == _LF) { |
| 71 index++; |
| 72 } |
| 73 codeBuffer.write('\n'); |
| 74 offset++; |
| 75 lineNo++; |
| 76 columnNo = 1; |
| 77 break; |
| 78 case 0x40: |
| 79 if (index + 1 < annotatedCode.length && |
| 80 annotatedCode.codeUnitAt(index + 1) == _LBRACE) { |
| 81 int endIndex = annotatedCode.indexOf('}', index); |
| 82 String text = annotatedCode.substring(index + 2, endIndex); |
| 83 annotations.add(new Annotation(lineNo, columnNo, offset, text)); |
| 84 index = endIndex; |
| 85 } else { |
| 86 codeBuffer.writeCharCode(charCode); |
| 87 offset++; |
| 88 columnNo++; |
| 89 } |
| 90 break; |
| 91 default: |
| 92 codeBuffer.writeCharCode(charCode); |
| 93 offset++; |
| 94 columnNo++; |
| 95 } |
| 96 index++; |
| 97 } |
| 98 return new AnnotatedCode.internal(codeBuffer.toString(), annotations); |
| 99 } |
| 100 } |
OLD | NEW |