| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library services.correction.change; | 5 library services.correction.change; |
| 6 | 6 |
| 7 import 'package:analysis_server/src/constants.dart'; | 7 import 'package:analysis_server/src/constants.dart'; |
| 8 import 'package:analysis_server/src/protocol2.dart'; |
| 8 import 'package:analysis_server/src/services/json.dart'; | 9 import 'package:analysis_server/src/services/json.dart'; |
| 9 import 'package:analyzer/src/generated/source.dart'; | 10 import 'package:analyzer/src/generated/source.dart'; |
| 10 | 11 |
| 11 | 12 |
| 12 /** | 13 /** |
| 13 * A description of a single change to one or more files. | 14 * A description of a single change to one or more files. |
| 14 */ | 15 */ |
| 15 class Change implements HasToJson { | 16 class Change implements HasToJson { |
| 16 /** | 17 /** |
| 17 * A textual description of the change to be applied. | 18 * A textual description of the change to be applied. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 31 /** | 32 /** |
| 32 * The position that should be selected after the edits have been applied. | 33 * The position that should be selected after the edits have been applied. |
| 33 */ | 34 */ |
| 34 Position selection; | 35 Position selection; |
| 35 | 36 |
| 36 Change(this.message); | 37 Change(this.message); |
| 37 | 38 |
| 38 /** | 39 /** |
| 39 * Adds [edit] to the [FileEdit] for the given [file]. | 40 * Adds [edit] to the [FileEdit] for the given [file]. |
| 40 */ | 41 */ |
| 41 void addEdit(String file, Edit edit) { | 42 void addEdit(String file, SourceEdit edit) { |
| 42 FileEdit fileEdit = getFileEdit(file); | 43 FileEdit fileEdit = getFileEdit(file); |
| 43 if (fileEdit == null) { | 44 if (fileEdit == null) { |
| 44 fileEdit = new FileEdit(file); | 45 fileEdit = new FileEdit(file); |
| 45 addFileEdit(fileEdit); | 46 addFileEdit(fileEdit); |
| 46 } | 47 } |
| 47 fileEdit.add(edit); | 48 fileEdit.add(edit); |
| 48 } | 49 } |
| 49 | 50 |
| 50 /** | 51 /** |
| 51 * Adds the given [FileEdit]. | 52 * Adds the given [FileEdit]. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 } | 88 } |
| 88 | 89 |
| 89 @override | 90 @override |
| 90 String toString() => | 91 String toString() => |
| 91 'Change(message=$message, edits=$fileEdits, ' | 92 'Change(message=$message, edits=$fileEdits, ' |
| 92 'linkedEditGroups=$linkedEditGroups, selection=$selection)'; | 93 'linkedEditGroups=$linkedEditGroups, selection=$selection)'; |
| 93 } | 94 } |
| 94 | 95 |
| 95 | 96 |
| 96 /** | 97 /** |
| 97 * A description of a single change to a single file. | 98 * Convert a SourceRange to a SourceEdit. |
| 98 */ | 99 */ |
| 99 class Edit implements HasToJson { | 100 SourceEdit editFromRange(SourceRange range, String replacement, {String id}) => |
| 100 /** | 101 new SourceEdit(range.offset, range.length, replacement, id: id); |
| 101 * The offset of the region to be modified. | |
| 102 */ | |
| 103 final int offset; | |
| 104 | 102 |
| 105 /** | 103 /** |
| 106 * The length of the region to be modified. | 104 * Get the result of applying the edit to the given [code]. |
| 107 */ | 105 */ |
| 108 final int length; | 106 String applyEdit(String code, SourceEdit edit) { |
| 107 return code.substring(0, edit.offset) + edit.replacement + |
| 108 code.substring(edit.offset + edit.length); |
| 109 } |
| 109 | 110 |
| 110 /** | 111 /** |
| 111 * The text that is to replace the specified region in the original text. | 112 * Get the result of applying a set of [edits] to the given [code]. Edits |
| 112 */ | 113 * are applied in the order they appear in [edits]. |
| 113 final String replacement; | 114 */ |
| 114 | 115 String applySequence(String code, Iterable<SourceEdit> edits) { |
| 115 /** | 116 edits.forEach((SourceEdit edit) { |
| 116 * An identifier that uniquely identifies this source edit from other edits in | 117 code = applyEdit(code, edit); |
| 117 * the same response. This field is omitted unless a containing structure | 118 }); |
| 118 * needs to be able to identify the edit for some reason. | 119 return code; |
| 119 * | |
| 120 * For example, some refactoring operations can produce edits that might not | |
| 121 * be appropriate (referred to as potential edits). Such edits will have an id | |
| 122 * so that they can be referenced. Edits in the same response that do not need | |
| 123 * to be referenced will not have an id. | |
| 124 */ | |
| 125 String id; | |
| 126 | |
| 127 Edit(this.offset, this.length, this.replacement); | |
| 128 | |
| 129 Edit.range(SourceRange range, String replacement) | |
| 130 : this(range.offset, range.length, replacement); | |
| 131 | |
| 132 /** | |
| 133 * The offset of a character immediately after the region to be modified. | |
| 134 */ | |
| 135 int get end => offset + length; | |
| 136 | |
| 137 bool operator ==(other) { | |
| 138 if (other is Edit) { | |
| 139 return other.offset == offset && | |
| 140 other.length == length && | |
| 141 other.replacement == replacement; | |
| 142 } | |
| 143 return false; | |
| 144 } | |
| 145 | |
| 146 /** | |
| 147 * Get the result of applying the edit to the given [code]. | |
| 148 */ | |
| 149 String apply(String code) { | |
| 150 return code.substring(0, offset) + replacement + code.substring(end); | |
| 151 } | |
| 152 | |
| 153 @override | |
| 154 Map<String, Object> toJson() { | |
| 155 return { | |
| 156 OFFSET: offset, | |
| 157 LENGTH: length, | |
| 158 REPLACEMENT: replacement | |
| 159 }; | |
| 160 } | |
| 161 | |
| 162 @override | |
| 163 String toString() { | |
| 164 StringBuffer sb = new StringBuffer(); | |
| 165 sb.write('Edit(offset='); | |
| 166 sb.write(offset); | |
| 167 sb.write(', length='); | |
| 168 sb.write(length); | |
| 169 sb.write(', replacement=:>'); | |
| 170 sb.write(replacement); | |
| 171 sb.write('<:'); | |
| 172 if (id != null) { | |
| 173 sb.write(', id='); | |
| 174 sb.write(id); | |
| 175 } | |
| 176 sb.write(')'); | |
| 177 return sb.toString(); | |
| 178 } | |
| 179 | |
| 180 /** | |
| 181 * Get the result of applying a set of [edits] to the given [code]. Edits | |
| 182 * are applied in the order they appear in [edits]. | |
| 183 */ | |
| 184 static String applySequence(String code, Iterable<Edit> edits) { | |
| 185 edits.forEach((Edit edit) { | |
| 186 code = edit.apply(code); | |
| 187 }); | |
| 188 return code; | |
| 189 } | |
| 190 } | 120 } |
| 191 | 121 |
| 192 | 122 |
| 193 /** | 123 /** |
| 194 * A description of a set of changes to a single file. | 124 * A description of a set of changes to a single file. |
| 195 * | 125 * |
| 196 * [Edit]s are added in the order of decreasing offset, so they are easy to | 126 * [Edit]s are added in the order of decreasing offset, so they are easy to |
| 197 * apply to the original file content without correcting offsets. | 127 * apply to the original file content without correcting offsets. |
| 198 */ | 128 */ |
| 199 class FileEdit implements HasToJson { | 129 class FileEdit implements HasToJson { |
| 200 /** | 130 /** |
| 201 * The file to be modified. | 131 * The file to be modified. |
| 202 */ | 132 */ |
| 203 final String file; | 133 final String file; |
| 204 | 134 |
| 205 /** | 135 /** |
| 206 * A list of the [Edit]s used to effect the change. | 136 * A list of the [Edit]s used to effect the change. |
| 207 */ | 137 */ |
| 208 final List<Edit> edits = <Edit>[]; | 138 final List<SourceEdit> edits = <SourceEdit>[]; |
| 209 | 139 |
| 210 FileEdit(this.file); | 140 FileEdit(this.file); |
| 211 | 141 |
| 212 /** | 142 /** |
| 213 * Adds the given [Edit] to the list. | 143 * Adds the given [Edit] to the list. |
| 214 */ | 144 */ |
| 215 void add(Edit edit) { | 145 void add(SourceEdit edit) { |
| 216 int index = 0; | 146 int index = 0; |
| 217 while (index < edits.length && edits[index].offset > edit.offset) { | 147 while (index < edits.length && edits[index].offset > edit.offset) { |
| 218 index++; | 148 index++; |
| 219 } | 149 } |
| 220 edits.insert(index, edit); | 150 edits.insert(index, edit); |
| 221 } | 151 } |
| 222 | 152 |
| 223 /** | 153 /** |
| 224 * Adds the given [Edit]s. | 154 * Adds the given [Edit]s. |
| 225 */ | 155 */ |
| 226 void addAll(Iterable<Edit> edits) { | 156 void addAll(Iterable<SourceEdit> edits) { |
| 227 edits.forEach(add); | 157 edits.forEach(add); |
| 228 } | 158 } |
| 229 | 159 |
| 230 @override | 160 @override |
| 231 Map<String, Object> toJson() { | 161 Map<String, Object> toJson() { |
| 232 return { | 162 return { |
| 233 FILE: file, | 163 FILE: file, |
| 234 EDITS: objectToJson(edits) | 164 EDITS: objectToJson(edits) |
| 235 }; | 165 }; |
| 236 } | 166 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 Map<String, Object> toJson() { | 282 Map<String, Object> toJson() { |
| 353 return { | 283 return { |
| 354 FILE: file, | 284 FILE: file, |
| 355 OFFSET: offset | 285 OFFSET: offset |
| 356 }; | 286 }; |
| 357 } | 287 } |
| 358 | 288 |
| 359 @override | 289 @override |
| 360 String toString() => 'Position(file=$file, offset=$offset)'; | 290 String toString() => 'Position(file=$file, offset=$offset)'; |
| 361 } | 291 } |
| OLD | NEW |