Skip to content

Commit 65b7aea

Browse files
committed
Correctly compute offsets when text contains non-ASCII characters
1 parent abc2bf0 commit 65b7aea

1 file changed

Lines changed: 15 additions & 11 deletions

File tree

clang-format/ClangFormatCommand.mm

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
// Generates a list of offsets for ever line in the array.
88
void updateOffsets(std::vector<size_t>& offsets, NSMutableArray<NSString*>* lines) {
99
offsets.clear();
10-
offsets.reserve(lines.count + 1);
10+
offsets.reserve(lines.count + 2);
1111
offsets.push_back(0);
1212
size_t offset = 0;
1313
for (NSString* line in lines) {
14-
offsets.push_back(offset += line.length);
14+
offsets.push_back(offset += [line lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
1515
}
16+
offsets.push_back(offset);
1617
}
1718

1819
clang::format::FormatStyle::LanguageKind getLanguageKind(XCSourceTextBuffer* buffer) {
@@ -227,6 +228,9 @@ - (void)performCommandWithInvocation:(XCSourceEditorCommandInvocation*)invocatio
227228
continue;
228229
}
229230

231+
// We're adding a final offset index that is the position beyond the last byte.
232+
assert(end_it + 1 != offsets.end());
233+
230234
// We need to go one line back unless we're at the beginning of the line.
231235
if (*start_it > start) {
232236
--start_it;
@@ -237,18 +241,18 @@ - (void)performCommandWithInvocation:(XCSourceEditorCommandInvocation*)invocatio
237241

238242
const size_t start_line = std::distance(offsets.begin(), start_it);
239243
const int64_t start_column = int64_t(start) - int64_t(*start_it);
244+
assert(start_column >= 0);
240245

241246
const size_t end_line = std::distance(offsets.begin(), end_it);
242247
const int64_t end_column = int64_t(end) - int64_t(*end_it);
243-
244-
NSString* before = [[lines objectAtIndex:start_line] substringToIndex:start_column];
245-
NSString* changed = [[NSString alloc] initWithBytes:replacement.data()
246-
length:replacement.size()
247-
encoding:NSUTF8StringEncoding];
248-
NSString* after = end_line >= lines.count
249-
? @""
250-
: [[lines objectAtIndex:end_line] substringFromIndex:end_column];
251-
NSString* string = [@[ before, changed, after ] componentsJoinedByString:@""];
248+
assert(end_column >= 0);
249+
NSData* before_line = [[lines objectAtIndex:start_line] dataUsingEncoding:NSUTF8StringEncoding];
250+
NSData* after_line = [[lines objectAtIndex:end_line] dataUsingEncoding:NSUTF8StringEncoding];
251+
NSMutableData* replacement_data = [[NSMutableData alloc] initWithBytes:before_line.bytes length:start_column];
252+
[replacement_data appendBytes:replacement.data() length:replacement.size()];
253+
[replacement_data appendBytes:(reinterpret_cast<const char*>(after_line.bytes) + end_column) length: (after_line.length - end_column)];
254+
255+
NSString* string = [[NSString alloc] initWithData:replacement_data encoding:NSUTF8StringEncoding];
252256
NSMutableArray* replacements = [[NSMutableArray alloc] init];
253257
[string
254258
enumerateSubstringsInRange:NSMakeRange(0, string.length)

0 commit comments

Comments
 (0)