Also, revert unintentional changes to fixtures. Changes to test fixtures are intentional and necessary. Release Notes: - N/A
Unified · Split
| @@ -9132,7 +9132,7 @@ impl Editor { · 9131 unmodified lines | |||
| 9132 | window: &mut Window, | 9132 | window: &mut Window, |
| 9133 | cx: &mut Context<Self>, | 9133 | cx: &mut Context<Self>, |
| 9134 | ) { | 9134 | ) { |
| 9135 | self.manipulate_immutable_lines(window, cx, |lines| lines.sort()) | 9135 | self.manipulate_lines(window, cx, |lines| lines.sort()) |
| 9136 | } | 9136 | } |
| 9137 | 9137 | ||
| 9138 | pub fn sort_lines_case_insensitive( | 9138 | pub fn sort_lines_case_insensitive( |
| @@ -9141,7 +9141,7 @@ impl Editor { · 2 unmodified lines | |||
| 9141 | window: &mut Window, | 9141 | window: &mut Window, |
| 9142 | cx: &mut Context<Self>, | 9142 | cx: &mut Context<Self>, |
| 9143 | ) { | 9143 | ) { |
| 9144 | self.manipulate_immutable_lines(window, cx, |lines| { | 9144 | self.manipulate_lines(window, cx, |lines| { |
| 9145 | lines.sort_by_key(|line| line.to_lowercase()) | 9145 | lines.sort_by_key(|line| line.to_lowercase()) |
| 9146 | }) | 9146 | }) |
| 9147 | } | 9147 | } |
| @@ -9152,7 +9152,7 @@ impl Editor { · 4 unmodified lines | |||
| 9152 | window: &mut Window, | 9152 | window: &mut Window, |
| 9153 | cx: &mut Context<Self>, | 9153 | cx: &mut Context<Self>, |
| 9154 | ) { | 9154 | ) { |
| 9155 | self.manipulate_immutable_lines(window, cx, |lines| { | 9155 | self.manipulate_lines(window, cx, |lines| { |
| 9156 | let mut seen = HashSet::default(); | 9156 | let mut seen = HashSet::default(); |
| 9157 | lines.retain(|line| seen.insert(line.to_lowercase())); | 9157 | lines.retain(|line| seen.insert(line.to_lowercase())); |
| 9158 | }) | 9158 | }) |
| @@ -9164,7 +9164,7 @@ impl Editor { · 5 unmodified lines | |||
| 9164 | window: &mut Window, | 9164 | window: &mut Window, |
| 9165 | cx: &mut Context<Self>, | 9165 | cx: &mut Context<Self>, |
| 9166 | ) { | 9166 | ) { |
| 9167 | self.manipulate_immutable_lines(window, cx, |lines| { | 9167 | self.manipulate_lines(window, cx, |lines| { |
| 9168 | let mut seen = HashSet::default(); | 9168 | let mut seen = HashSet::default(); |
| 9169 | lines.retain(|line| seen.insert(*line)); | 9169 | lines.retain(|line| seen.insert(*line)); |
| 9170 | }) | 9170 | }) |
| @@ -9606,20 +9606,20 @@ impl Editor { · 435 unmodified lines | |||
| 9606 | } | 9606 | } |
| 9607 | 9607 | ||
| 9608 | pub fn reverse_lines(&mut self, _: &ReverseLines, window: &mut Window, cx: &mut Context<Self>) { | 9608 | pub fn reverse_lines(&mut self, _: &ReverseLines, window: &mut Window, cx: &mut Context<Self>) { |
| 9609 | self.manipulate_immutable_lines(window, cx, |lines| lines.reverse()) | 9609 | self.manipulate_lines(window, cx, |lines| lines.reverse()) |
| 9610 | } | 9610 | } |
| 9611 | 9611 | ||
| 9612 | pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) { | 9612 | pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) { |
| 9613 | self.manipulate_immutable_lines(window, cx, |lines| lines.shuffle(&mut thread_rng())) | 9613 | self.manipulate_lines(window, cx, |lines| lines.shuffle(&mut thread_rng())) |
| 9614 | } | 9614 | } |
| 9615 | 9615 | ||
| 9616 | fn manipulate_lines<M>( | 9616 | fn manipulate_lines<Fn>( |
| 9617 | &mut self, | 9617 | &mut self, |
| 9618 | window: &mut Window, | 9618 | window: &mut Window, |
| 9619 | cx: &mut Context<Self>, | 9619 | cx: &mut Context<Self>, |
| 9620 | mut manipulate: M, | 9620 | mut callback: Fn, |
| 9621 | ) where | 9621 | ) where |
| 9622 | M: FnMut(&str) -> LineManipulationResult, | 9622 | Fn: FnMut(&mut Vec<&str>), |
| 9623 | { | 9623 | { |
| 9624 | self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction); | 9624 | self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction); |
| 9625 | 9625 | ||
| @@ -9652,14 +9652,18 @@ impl Editor { · 26 unmodified lines | |||
| 9652 | .text_for_range(start_point..end_point) | 9652 | .text_for_range(start_point..end_point) |
| 9653 | .collect::<String>(); | 9653 | .collect::<String>(); |
| 9654 | 9654 | ||
| 9655 | let LineManipulationResult { new_text, line_count_before, line_count_after} = manipulate(&text); | 9655 | let mut lines = text.split('\n').collect_vec(); |
| 9656 | 9656 | ||
| 9657 | edits.push((start_point..end_point, new_text)); | 9657 | let lines_before = lines.len(); |
| 9658 | callback(&mut lines); | ||
| 9659 | let lines_after = lines.len(); | ||
| 9660 | |||
| 9661 | edits.push((start_point..end_point, lines.join("\n"))); | ||
| 9658 | 9662 | ||
| 9659 | // Selections must change based on added and removed line count | 9663 | // Selections must change based on added and removed line count |
| 9660 | let start_row = | 9664 | let start_row = |
| 9661 | MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32); | 9665 | MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32); |
| 9662 | let end_row = MultiBufferRow(start_row.0 + line_count_after.saturating_sub(1) as u32); | 9666 | let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32); |
| 9663 | new_selections.push(Selection { | 9667 | new_selections.push(Selection { |
| 9664 | id: selection.id, | 9668 | id: selection.id, |
| 9665 | start: start_row, | 9669 | start: start_row, |
| @@ -9668,10 +9672,10 @@ impl Editor { · 2 unmodified lines | |||
| 9668 | reversed: selection.reversed, | 9672 | reversed: selection.reversed, |
| 9669 | }); | 9673 | }); |
| 9670 | 9674 | ||
| 9671 | if line_count_after > line_count_before { | 9675 | if lines_after > lines_before { |
| 9672 | added_lines += line_count_after - line_count_before; | 9676 | added_lines += lines_after - lines_before; |
| 9673 | } else if line_count_before > line_count_after { | 9677 | } else if lines_before > lines_after { |
| 9674 | removed_lines += line_count_before - line_count_after; | 9678 | removed_lines += lines_before - lines_after; |
| 9675 | } | 9679 | } |
| 9676 | } | 9680 | } |
| 9677 | 9681 | ||
| @@ -9716,171 +9720,6 @@ impl Editor { · 38 unmodified lines | |||
| 9716 | }) | 9720 | }) |
| 9717 | } | 9721 | } |
| 9718 | 9722 | ||
| 9719 | fn manipulate_immutable_lines<Fn>( | ||
| 9720 | &mut self, | ||
| 9721 | window: &mut Window, | ||
| 9722 | cx: &mut Context<Self>, | ||
| 9723 | mut callback: Fn, | ||
| 9724 | ) where | ||
| 9725 | Fn: FnMut(&mut Vec<&str>), | ||
| 9726 | { | ||
| 9727 | self.manipulate_lines(window, cx, |text| { | ||
| 9728 | let mut lines: Vec<&str> = text.split('\n').collect(); | ||
| 9729 | let line_count_before = lines.len(); | ||
| 9730 | |||
| 9731 | callback(&mut lines); | ||
| 9732 | |||
| 9733 | LineManipulationResult { | ||
| 9734 | new_text: lines.join("\n"), | ||
| 9735 | line_count_before, | ||
| 9736 | line_count_after: lines.len(), | ||
| 9737 | } | ||
| 9738 | }); | ||
| 9739 | } | ||
| 9740 | |||
| 9741 | fn manipulate_mutable_lines<Fn>( | ||
| 9742 | &mut self, | ||
| 9743 | window: &mut Window, | ||
| 9744 | cx: &mut Context<Self>, | ||
| 9745 | mut callback: Fn, | ||
| 9746 | ) where | ||
| 9747 | Fn: FnMut(&mut Vec<Cow<'_, str>>), | ||
| 9748 | { | ||
| 9749 | self.manipulate_lines(window, cx, |text| { | ||
| 9750 | let mut lines: Vec<Cow<str>> = text.split('\n').map(Cow::from).collect(); | ||
| 9751 | let line_count_before = lines.len(); | ||
| 9752 | |||
| 9753 | callback(&mut lines); | ||
| 9754 | |||
| 9755 | LineManipulationResult { | ||
| 9756 | new_text: lines.join("\n"), | ||
| 9757 | line_count_before, | ||
| 9758 | line_count_after: lines.len(), | ||
| 9759 | } | ||
| 9760 | }); | ||
| 9761 | } | ||
| 9762 | |||
| 9763 | pub fn convert_indentation_to_spaces( | ||
| 9764 | &mut self, | ||
| 9765 | _: &ConvertIndentationToSpaces, | ||
| 9766 | window: &mut Window, | ||
| 9767 | cx: &mut Context<Self>, | ||
| 9768 | ) { | ||
| 9769 | let settings = self.buffer.read(cx).language_settings(cx); | ||
| 9770 | let tab_size = settings.tab_size.get() as usize; | ||
| 9771 | |||
| 9772 | self.manipulate_mutable_lines(window, cx, |lines| { | ||
| 9773 | // Allocates a reasonably sized scratch buffer once for the whole loop | ||
| 9774 | let mut reindented_line = String::with_capacity(MAX_LINE_LEN); | ||
| 9775 | // Avoids recomputing spaces that could be inserted many times | ||
| 9776 | let space_cache: Vec<Vec<char>> = (1..=tab_size) | ||
| 9777 | .map(|n| IndentSize::spaces(n as u32).chars().collect()) | ||
| 9778 | .collect(); | ||
| 9779 | |||
| 9780 | for line in lines.iter_mut().filter(|line| !line.is_empty()) { | ||
| 9781 | let mut chars = line.as_ref().chars(); | ||
| 9782 | let mut col = 0; | ||
| 9783 | let mut changed = false; | ||
| 9784 | |||
| 9785 | while let Some(ch) = chars.next() { | ||
| 9786 | match ch { | ||
| 9787 | ' ' => { | ||
| 9788 | reindented_line.push(' '); | ||
| 9789 | col += 1; | ||
| 9790 | } | ||
| 9791 | '\t' => { | ||
| 9792 | // \t are converted to spaces depending on the current column | ||
| 9793 | let spaces_len = tab_size - (col % tab_size); | ||
| 9794 | reindented_line.extend(&space_cache[spaces_len - 1]); | ||
| 9795 | col += spaces_len; | ||
| 9796 | changed = true; | ||
| 9797 | } | ||
| 9798 | _ => { | ||
| 9799 | // If we dont append before break, the character is consumed | ||
| 9800 | reindented_line.push(ch); | ||
| 9801 | break; | ||
| 9802 | } | ||
| 9803 | } | ||
| 9804 | } | ||
| 9805 | |||
| 9806 | if !changed { | ||
| 9807 | reindented_line.clear(); | ||
| 9808 | continue; | ||
| 9809 | } | ||
| 9810 | // Append the rest of the line and replace old reference with new one | ||
| 9811 | reindented_line.extend(chars); | ||
| 9812 | *line = Cow::Owned(reindented_line.clone()); | ||
| 9813 | reindented_line.clear(); | ||
| 9814 | } | ||
| 9815 | }); | ||
| 9816 | } | ||
| 9817 | |||
| 9818 | pub fn convert_indentation_to_tabs( | ||
| 9819 | &mut self, | ||
| 9820 | _: &ConvertIndentationToTabs, | ||
| 9821 | window: &mut Window, | ||
| 9822 | cx: &mut Context<Self>, | ||
| 9823 | ) { | ||
| 9824 | let settings = self.buffer.read(cx).language_settings(cx); | ||
| 9825 | let tab_size = settings.tab_size.get() as usize; | ||
| 9826 | |||
| 9827 | self.manipulate_mutable_lines(window, cx, |lines| { | ||
| 9828 | // Allocates a reasonably sized buffer once for the whole loop | ||
| 9829 | let mut reindented_line = String::with_capacity(MAX_LINE_LEN); | ||
| 9830 | // Avoids recomputing spaces that could be inserted many times | ||
| 9831 | let space_cache: Vec<Vec<char>> = (1..=tab_size) | ||
| 9832 | .map(|n| IndentSize::spaces(n as u32).chars().collect()) | ||
| 9833 | .collect(); | ||
| 9834 | |||
| 9835 | for line in lines.iter_mut().filter(|line| !line.is_empty()) { | ||
| 9836 | let mut chars = line.chars(); | ||
| 9837 | let mut spaces_count = 0; | ||
| 9838 | let mut first_non_indent_char = None; | ||
| 9839 | let mut changed = false; | ||
| 9840 | |||
| 9841 | while let Some(ch) = chars.next() { | ||
| 9842 | match ch { | ||
| 9843 | ' ' => { | ||
| 9844 | // Keep track of spaces. Append \t when we reach tab_size | ||
| 9845 | spaces_count += 1; | ||
| 9846 | changed = true; | ||
| 9847 | if spaces_count == tab_size { | ||
| 9848 | reindented_line.push('\t'); | ||
| 9849 | spaces_count = 0; | ||
| 9850 | } | ||
| 9851 | } | ||
| 9852 | '\t' => { | ||
| 9853 | reindented_line.push('\t'); | ||
| 9854 | spaces_count = 0; | ||
| 9855 | } | ||
| 9856 | _ => { | ||
| 9857 | // Dont append it yet, we might have remaining spaces | ||
| 9858 | first_non_indent_char = Some(ch); | ||
| 9859 | break; | ||
| 9860 | } | ||
| 9861 | } | ||
| 9862 | } | ||
| 9863 | |||
| 9864 | if !changed { | ||
| 9865 | reindented_line.clear(); | ||
| 9866 | continue; | ||
| 9867 | } | ||
| 9868 | // Remaining spaces that didn't make a full tab stop | ||
| 9869 | if spaces_count > 0 { | ||
| 9870 | reindented_line.extend(&space_cache[spaces_count - 1]); | ||
| 9871 | } | ||
| 9872 | // If we consume an extra character that was not indentation, add it back | ||
| 9873 | if let Some(extra_char) = first_non_indent_char { | ||
| 9874 | reindented_line.push(extra_char); | ||
| 9875 | } | ||
| 9876 | // Append the rest of the line and replace old reference with new one | ||
| 9877 | reindented_line.extend(chars); | ||
| 9878 | *line = Cow::Owned(reindented_line.clone()); | ||
| 9879 | reindented_line.clear(); | ||
| 9880 | } | ||
| 9881 | }); | ||
| 9882 | } | ||
| 9883 | |||
| 9884 | pub fn convert_to_upper_case( | 9723 | pub fn convert_to_upper_case( |
| 9885 | &mut self, | 9724 | &mut self, |
| 9886 | _: &ConvertToUpperCase, | 9725 | _: &ConvertToUpperCase, |
| @@ -21318,13 +21157,6 @@ pub struct LineHighlight { · 11431 unmodified lines | |||
| 21318 | pub type_id: Option<TypeId>, | 21157 | pub type_id: Option<TypeId>, |
| 21319 | } | 21158 | } |
| 21320 | 21159 | ||
| 21321 | struct LineManipulationResult { | ||
| 21322 | pub new_text: String, | ||
| 21323 | pub line_count_before: usize, | ||
| 21324 | pub line_count_after: usize, | ||
| 21325 | } | ||
| 21326 | |||
| 21327 | |||
| 21328 | fn render_diff_hunk_controls( | 21160 | fn render_diff_hunk_controls( |
| 21329 | row: u32, | 21161 | row: u32, |
| 21330 | status: &DiffHunkStatus, | 21162 | status: &DiffHunkStatus, |
| @@ -94,3 +94,24 @@ for (const promptPath of modifiedPrompts) { · 93 unmodified lines | |||
| 94 | ); | 94 | ); |
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | |||
| 98 | const FIXTURE_CHANGE_ATTESTATION = "Changes to test fixtures are intentional and necessary."; | ||
| 99 | |||
| 100 | const FIXTURES_PATHS = ["crates/assistant_tools/src/edit_agent/evals/fixtures"]; | ||
| 101 | |||
| 102 | const modifiedFixtures = danger.git.modified_files.filter((file) => | ||
| 103 | FIXTURES_PATHS.some((fixturePath) => file.includes(fixturePath)), | ||
| 104 | ); | ||
| 105 | |||
| 106 | if (modifiedFixtures.length > 0) { | ||
| 107 | if (!body.includes(FIXTURE_CHANGE_ATTESTATION)) { | ||
| 108 | const modifiedFixturesStr = modifiedFixtures.map((path) => "`" + path + "`").join(", "); | ||
| 109 | fail( | ||
| 110 | [ | ||
| 111 | `This PR modifies eval or test fixtures (${modifiedFixturesStr}), which are typically expected to remain unchanged.`, | ||
| 112 | "If these changes are intentional and required, please add the following attestation to your PR description: ", | ||
| 113 | `"${FIXTURE_CHANGE_ATTESTATION}"`, | ||
| 114 | ].join("\n\n"), | ||
| 115 | ); | ||
| 116 | } | ||
| 117 | } | ||