| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 const int _LF = 0x0A; | 5 const int _LF = 0x0A; |
| 6 const int _CR = 0x0D; | 6 const int _CR = 0x0D; |
| 7 const int _LBRACE = 0x7B; | 7 const int _LBRACE = 0x7B; |
| 8 | 8 |
| 9 class Annotation { | 9 class Annotation { |
| 10 /// 1-based line number of the annotation. | 10 /// 1-based line number of the annotation. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 /// 'bar-args'. | 37 /// 'bar-args'. |
| 38 /// | 38 /// |
| 39 /// Annotation text cannot span multiple lines and cannot contain '}'. | 39 /// Annotation text cannot span multiple lines and cannot contain '}'. |
| 40 class AnnotatedCode { | 40 class AnnotatedCode { |
| 41 /// The source code without annotations. | 41 /// The source code without annotations. |
| 42 final String sourceCode; | 42 final String sourceCode; |
| 43 | 43 |
| 44 /// The annotations for the source code. | 44 /// The annotations for the source code. |
| 45 final List<Annotation> annotations; | 45 final List<Annotation> annotations; |
| 46 | 46 |
| 47 AnnotatedCode.internal(this.sourceCode, this.annotations); | 47 List<int> _lineStarts; |
| 48 |
| 49 AnnotatedCode(this.sourceCode, this.annotations); |
| 50 |
| 51 AnnotatedCode.internal(this.sourceCode, this.annotations, this._lineStarts); |
| 48 | 52 |
| 49 /// Creates an [AnnotatedCode] by processing [annotatedCode]. Annotation of | 53 /// Creates an [AnnotatedCode] by processing [annotatedCode]. Annotation of |
| 50 /// the form `@{...}` are converted into [Annotation]s and removed from the | 54 /// the form `@{...}` are converted into [Annotation]s and removed from the |
| 51 /// [annotatedCode] to process the source code. | 55 /// [annotatedCode] to process the source code. |
| 52 factory AnnotatedCode(String annotatedCode) { | 56 factory AnnotatedCode.fromText(String annotatedCode) { |
| 53 StringBuffer codeBuffer = new StringBuffer(); | 57 StringBuffer codeBuffer = new StringBuffer(); |
| 54 List<Annotation> annotations = <Annotation>[]; | 58 List<Annotation> annotations = <Annotation>[]; |
| 55 int index = 0; | 59 int index = 0; |
| 56 int offset = 0; | 60 int offset = 0; |
| 57 int lineNo = 1; | 61 int lineNo = 1; |
| 58 int columnNo = 1; | 62 int columnNo = 1; |
| 63 List<int> lineStarts = <int>[]; |
| 64 lineStarts.add(offset); |
| 59 while (index < annotatedCode.length) { | 65 while (index < annotatedCode.length) { |
| 60 int charCode = annotatedCode.codeUnitAt(index); | 66 int charCode = annotatedCode.codeUnitAt(index); |
| 61 switch (charCode) { | 67 switch (charCode) { |
| 62 case _LF: | 68 case _LF: |
| 63 codeBuffer.write('\n'); | 69 codeBuffer.write('\n'); |
| 64 offset++; | 70 offset++; |
| 71 lineStarts.add(offset); |
| 65 lineNo++; | 72 lineNo++; |
| 66 columnNo = 1; | 73 columnNo = 1; |
| 67 break; | 74 break; |
| 68 case _CR: | 75 case _CR: |
| 69 if (index + 1 < annotatedCode.length && | 76 if (index + 1 < annotatedCode.length && |
| 70 annotatedCode.codeUnitAt(index + 1) == _LF) { | 77 annotatedCode.codeUnitAt(index + 1) == _LF) { |
| 71 index++; | 78 index++; |
| 72 } | 79 } |
| 73 codeBuffer.write('\n'); | 80 codeBuffer.write('\n'); |
| 74 offset++; | 81 offset++; |
| 82 lineStarts.add(offset); |
| 75 lineNo++; | 83 lineNo++; |
| 76 columnNo = 1; | 84 columnNo = 1; |
| 77 break; | 85 break; |
| 78 case 0x40: | 86 case 0x40: |
| 79 if (index + 1 < annotatedCode.length && | 87 if (index + 1 < annotatedCode.length && |
| 80 annotatedCode.codeUnitAt(index + 1) == _LBRACE) { | 88 annotatedCode.codeUnitAt(index + 1) == _LBRACE) { |
| 81 int endIndex = annotatedCode.indexOf('}', index); | 89 int endIndex = annotatedCode.indexOf('}', index); |
| 82 String text = annotatedCode.substring(index + 2, endIndex); | 90 String text = annotatedCode.substring(index + 2, endIndex); |
| 83 annotations.add(new Annotation(lineNo, columnNo, offset, text)); | 91 annotations.add(new Annotation(lineNo, columnNo, offset, text)); |
| 84 index = endIndex; | 92 index = endIndex; |
| 85 } else { | 93 } else { |
| 86 codeBuffer.writeCharCode(charCode); | 94 codeBuffer.writeCharCode(charCode); |
| 87 offset++; | 95 offset++; |
| 88 columnNo++; | 96 columnNo++; |
| 89 } | 97 } |
| 90 break; | 98 break; |
| 91 default: | 99 default: |
| 92 codeBuffer.writeCharCode(charCode); | 100 codeBuffer.writeCharCode(charCode); |
| 93 offset++; | 101 offset++; |
| 94 columnNo++; | 102 columnNo++; |
| 95 } | 103 } |
| 96 index++; | 104 index++; |
| 97 } | 105 } |
| 98 return new AnnotatedCode.internal(codeBuffer.toString(), annotations); | 106 lineStarts.add(offset); |
| 107 return new AnnotatedCode.internal( |
| 108 codeBuffer.toString(), annotations, lineStarts); |
| 109 } |
| 110 |
| 111 void _ensureLineStarts() { |
| 112 if (_lineStarts == null) { |
| 113 int index = 0; |
| 114 int offset = 0; |
| 115 _lineStarts = <int>[]; |
| 116 _lineStarts.add(offset); |
| 117 while (index < sourceCode.length) { |
| 118 int charCode = sourceCode.codeUnitAt(index); |
| 119 switch (charCode) { |
| 120 case _LF: |
| 121 offset++; |
| 122 _lineStarts.add(offset); |
| 123 break; |
| 124 case _CR: |
| 125 if (index + 1 < sourceCode.length && |
| 126 sourceCode.codeUnitAt(index + 1) == _LF) { |
| 127 index++; |
| 128 } |
| 129 offset++; |
| 130 _lineStarts.add(offset); |
| 131 break; |
| 132 default: |
| 133 offset++; |
| 134 } |
| 135 index++; |
| 136 } |
| 137 _lineStarts.add(offset); |
| 138 } |
| 139 } |
| 140 |
| 141 void addAnnotation(int lineNo, int columnNo, String text) { |
| 142 _ensureLineStarts(); |
| 143 int offset = _lineStarts[lineNo - 1] + (columnNo - 1); |
| 144 annotations.add(new Annotation(lineNo, columnNo, offset, text)); |
| 145 } |
| 146 |
| 147 String toText() { |
| 148 StringBuffer sb = new StringBuffer(); |
| 149 List<Annotation> list = annotations.toList() |
| 150 ..sort((a, b) => a.offset.compareTo(b.offset)); |
| 151 int offset = 0; |
| 152 for (Annotation annotation in list) { |
| 153 sb.write(sourceCode.substring(offset, annotation.offset)); |
| 154 sb.write('@{${annotation.text}}'); |
| 155 offset = annotation.offset; |
| 156 } |
| 157 sb.write(sourceCode.substring(offset)); |
| 158 return sb.toString(); |
| 99 } | 159 } |
| 100 } | 160 } |
| OLD | NEW |