| 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_services/constants.dart'; | 7 import 'package:analysis_services/constants.dart'; |
| 8 import 'package:analysis_services/json.dart'; | 8 import 'package:analysis_services/json.dart'; |
| 9 import 'package:analyzer/src/generated/source.dart'; | 9 import 'package:analyzer/src/generated/source.dart'; |
| 10 import 'package:collection/collection.dart'; | 10 import 'package:collection/collection.dart'; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 EDITS: objectToJson(fileEdits), | 81 EDITS: objectToJson(fileEdits), |
| 82 LINKED_EDIT_GROUPS: objectToJson(linkedEditGroups) | 82 LINKED_EDIT_GROUPS: objectToJson(linkedEditGroups) |
| 83 }; | 83 }; |
| 84 if (selection != null) { | 84 if (selection != null) { |
| 85 json[SELECTION] = selection.toJson(); | 85 json[SELECTION] = selection.toJson(); |
| 86 } | 86 } |
| 87 return json; | 87 return json; |
| 88 } | 88 } |
| 89 | 89 |
| 90 @override | 90 @override |
| 91 String toString() => 'Change(message=$message, edits=$fileEdits, ' | 91 String toString() => |
| 92 'linkedEditGroups=$linkedEditGroups, selection=$selection)'; | 92 'Change(message=$message, edits=$fileEdits, ' |
| 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 * A description of a single change to a single file. |
| 98 */ | 99 */ |
| 99 class Edit implements HasToJson { | 100 class Edit implements HasToJson { |
| 100 /** | 101 /** |
| 101 * The offset of the region to be modified. | 102 * The offset of the region to be modified. |
| 102 */ | 103 */ |
| 103 final int offset; | 104 final int offset; |
| 104 | 105 |
| 105 /** | 106 /** |
| 106 * The length of the region to be modified. | 107 * The length of the region to be modified. |
| 107 */ | 108 */ |
| 108 final int length; | 109 final int length; |
| 109 | 110 |
| 110 /** | 111 /** |
| 111 * The text that is to replace the specified region in the original text. | 112 * The text that is to replace the specified region in the original text. |
| 112 */ | 113 */ |
| 113 final String replacement; | 114 final String replacement; |
| 114 | 115 |
| 115 Edit(this.offset, this.length, this.replacement); | 116 Edit(this.offset, this.length, this.replacement); |
| 116 | 117 |
| 117 Edit.range(SourceRange range, String replacement) : this(range.offset, | 118 Edit.range(SourceRange range, String replacement) : this( |
| 118 range.length, replacement); | 119 range.offset, |
| 120 range.length, |
| 121 replacement); |
| 119 | 122 |
| 120 /** | 123 /** |
| 121 * The offset of a character immediately after the region to be modified. | 124 * The offset of a character immediately after the region to be modified. |
| 122 */ | 125 */ |
| 123 int get end => offset + length; | 126 int get end => offset + length; |
| 124 | 127 |
| 125 bool operator ==(other) { | 128 bool operator ==(other) { |
| 126 if (other is Edit) { | 129 if (other is Edit) { |
| 127 return other.offset == offset && other.length == length && | 130 return other.offset == offset && |
| 131 other.length == length && |
| 128 other.replacement == replacement; | 132 other.replacement == replacement; |
| 129 } | 133 } |
| 130 return false; | 134 return false; |
| 131 } | 135 } |
| 132 | 136 |
| 137 /** |
| 138 * Get the result of applying the edit to the given [code]. |
| 139 */ |
| 140 String apply(String code) { |
| 141 return code.substring(0, offset) + replacement + code.substring(end); |
| 142 } |
| 143 |
| 133 @override | 144 @override |
| 134 Map<String, Object> toJson() { | 145 Map<String, Object> toJson() { |
| 135 return { | 146 return { |
| 136 OFFSET: offset, | 147 OFFSET: offset, |
| 137 LENGTH: length, | 148 LENGTH: length, |
| 138 REPLACEMENT: replacement | 149 REPLACEMENT: replacement |
| 139 }; | 150 }; |
| 140 } | 151 } |
| 141 | 152 |
| 142 @override | 153 @override |
| 143 String toString() => | 154 String toString() => |
| 144 "Edit(offset=$offset, length=$length, replacement=:>$replacement<:)"; | 155 "Edit(offset=$offset, length=$length, replacement=:>$replacement<:)"; |
| 145 | 156 |
| 146 /** | 157 /** |
| 147 * Get the result of applying the edit to the given [code]. | |
| 148 */ | |
| 149 String apply(String code) => code.substring(0, offset) + replacement + | |
| 150 code.substring(end); | |
| 151 | |
| 152 /** | |
| 153 * Get the result of applying a set of [edits] to the given [code]. Edits | 158 * Get the result of applying a set of [edits] to the given [code]. Edits |
| 154 * are applied in the order they appear in [edits]. | 159 * are applied in the order they appear in [edits]. |
| 155 */ | 160 */ |
| 156 static String applySequence(String code, Iterable<Edit> edits) { | 161 static String applySequence(String code, Iterable<Edit> edits) { |
| 157 edits.forEach((Edit edit) { | 162 edits.forEach((Edit edit) { |
| 158 code = edit.apply(code); | 163 code = edit.apply(code); |
| 159 }); | 164 }); |
| 160 return code; | 165 return code; |
| 161 } | 166 } |
| 162 | |
| 163 /** | |
| 164 * Get the result of applying a set of [edits] to the given [code]. Edits | |
| 165 * are applied in the order of decreasing offset. | |
| 166 */ | |
| 167 static String applySorted(String code, Iterable<Edit> edits) { | |
| 168 List<Edit> sortedEdits = edits.toList(); | |
| 169 mergeSort(sortedEdits, compare: (a, b) => a.offset - b.offset); | |
| 170 return Edit.applySequence(code, sortedEdits.reversed); | |
| 171 } | |
| 172 } | 167 } |
| 173 | 168 |
| 174 | 169 |
| 175 /** | 170 /** |
| 176 * A description of a set of changes to a single file. | 171 * A description of a set of changes to a single file. |
| 172 * |
| 173 * [Edit]s are added in the order of decreasing offset, so they are easy to |
| 174 * apply to the original file content without correcting offsets. |
| 177 */ | 175 */ |
| 178 class FileEdit implements HasToJson { | 176 class FileEdit implements HasToJson { |
| 179 /** | 177 /** |
| 180 * The file to be modified. | 178 * The file to be modified. |
| 181 */ | 179 */ |
| 182 final String file; | 180 final String file; |
| 183 | 181 |
| 184 /** | 182 /** |
| 185 * A list of the [Edit]s used to effect the change. | 183 * A list of the [Edit]s used to effect the change. |
| 186 */ | 184 */ |
| 187 final List<Edit> edits = <Edit>[]; | 185 final List<Edit> edits = <Edit>[]; |
| 188 | 186 |
| 189 FileEdit(this.file); | 187 FileEdit(this.file); |
| 190 | 188 |
| 191 /** | 189 /** |
| 192 * Adds the given [Edit] to the list. | 190 * Adds the given [Edit] to the list. |
| 193 */ | 191 */ |
| 194 void add(Edit edit) { | 192 void add(Edit edit) { |
| 195 edits.add(edit); | 193 int index = 0; |
| 194 while (index < edits.length && edits[index].offset > edit.offset) { |
| 195 index++; |
| 196 } |
| 197 edits.insert(index, edit); |
| 198 } |
| 199 |
| 200 /** |
| 201 * Adds the given [Edit]s. |
| 202 */ |
| 203 void addAll(Iterable<Edit> edits) { |
| 204 edits.forEach(add); |
| 196 } | 205 } |
| 197 | 206 |
| 198 @override | 207 @override |
| 199 Map<String, Object> toJson() { | 208 Map<String, Object> toJson() { |
| 200 return { | 209 return { |
| 201 FILE: file, | 210 FILE: file, |
| 202 EDITS: objectToJson(edits) | 211 EDITS: objectToJson(edits) |
| 203 }; | 212 }; |
| 204 } | 213 } |
| 205 | 214 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 234 Map<String, Object> toJson() { | 243 Map<String, Object> toJson() { |
| 235 return { | 244 return { |
| 236 ID: id, | 245 ID: id, |
| 237 LENGTH: length, | 246 LENGTH: length, |
| 238 POSITIONS: objectToJson(positions), | 247 POSITIONS: objectToJson(positions), |
| 239 SUGGESTIONS: objectToJson(suggestions) | 248 SUGGESTIONS: objectToJson(suggestions) |
| 240 }; | 249 }; |
| 241 } | 250 } |
| 242 | 251 |
| 243 @override | 252 @override |
| 244 String toString() => 'LinkedEditGroup(id=$id, length=$length, ' | 253 String toString() => |
| 245 'positions=$positions, suggestions=$suggestions)'; | 254 'LinkedEditGroup(id=$id, length=$length, ' |
| 255 'positions=$positions, suggestions=$suggestions)'; |
| 246 } | 256 } |
| 247 | 257 |
| 248 | 258 |
| 249 /** | 259 /** |
| 250 * A suggestion of a value that could be used to replace all of the linked edit | 260 * A suggestion of a value that could be used to replace all of the linked edit |
| 251 * regions in a [LinkedEditGroup]. | 261 * regions in a [LinkedEditGroup]. |
| 252 */ | 262 */ |
| 253 class LinkedEditSuggestion implements HasToJson { | 263 class LinkedEditSuggestion implements HasToJson { |
| 254 final LinkedEditSuggestionKind kind; | 264 final LinkedEditSuggestionKind kind; |
| 255 final String value; | 265 final String value; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 Map<String, Object> toJson() { | 329 Map<String, Object> toJson() { |
| 320 return { | 330 return { |
| 321 FILE: file, | 331 FILE: file, |
| 322 OFFSET: offset | 332 OFFSET: offset |
| 323 }; | 333 }; |
| 324 } | 334 } |
| 325 | 335 |
| 326 @override | 336 @override |
| 327 String toString() => 'Position(file=$file, offset=$offset)'; | 337 String toString() => 'Position(file=$file, offset=$offset)'; |
| 328 } | 338 } |
| OLD | NEW |