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 | 9132 | window: &mut Window, |
| 9133 | 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 | 9138 | pub fn sort_lines_case_insensitive( |
| @@ -9141,7 +9141,7 @@ impl Editor { · 2 unmodified lines | ||
| 9141 | 9141 | window: &mut Window, |
| 9142 | 9142 | cx: &mut Context<Self>, |
| 9143 | 9143 | ) { |
| 9144 | − self.manipulate_immutable_lines(window, cx, |lines| { | |
| 9144 | + self.manipulate_lines(window, cx, |lines| { | |
| 9145 | 9145 | lines.sort_by_key(|line| line.to_lowercase()) |
| 9146 | 9146 | }) |
| 9147 | 9147 | } |
| @@ -9152,7 +9152,7 @@ impl Editor { · 4 unmodified lines | ||
| 9152 | 9152 | window: &mut Window, |
| 9153 | 9153 | cx: &mut Context<Self>, |
| 9154 | 9154 | ) { |
| 9155 | − self.manipulate_immutable_lines(window, cx, |lines| { | |
| 9155 | + self.manipulate_lines(window, cx, |lines| { | |
| 9156 | 9156 | let mut seen = HashSet::default(); |
| 9157 | 9157 | lines.retain(|line| seen.insert(line.to_lowercase())); |
| 9158 | 9158 | }) |
| @@ -9164,7 +9164,7 @@ impl Editor { · 5 unmodified lines | ||
| 9164 | 9164 | window: &mut Window, |
| 9165 | 9165 | cx: &mut Context<Self>, |
| 9166 | 9166 | ) { |
| 9167 | − self.manipulate_immutable_lines(window, cx, |lines| { | |
| 9167 | + self.manipulate_lines(window, cx, |lines| { | |
| 9168 | 9168 | let mut seen = HashSet::default(); |
| 9169 | 9169 | lines.retain(|line| seen.insert(*line)); |
| 9170 | 9170 | }) |
| @@ -9606,20 +9606,20 @@ impl Editor { · 435 unmodified lines | ||
| 9606 | 9606 | } |
| 9607 | 9607 | |
| 9608 | 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 | 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 | 9617 | &mut self, |
| 9618 | 9618 | window: &mut Window, |
| 9619 | 9619 | cx: &mut Context<Self>, |
| 9620 | − mut manipulate: M, | |
| 9620 | + mut callback: Fn, | |
| 9621 | 9621 | ) where |
| 9622 | − M: FnMut(&str) -> LineManipulationResult, | |
| 9622 | + Fn: FnMut(&mut Vec<&str>), | |
| 9623 | 9623 | { |
| 9624 | 9624 | self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction); |
| 9625 | 9625 | |
| @@ -9652,14 +9652,18 @@ impl Editor { · 26 unmodified lines | ||
| 9652 | 9652 | .text_for_range(start_point..end_point) |
| 9653 | 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 | 9663 | // Selections must change based on added and removed line count |
| 9660 | 9664 | let start_row = |
| 9661 | 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 | 9667 | new_selections.push(Selection { |
| 9664 | 9668 | id: selection.id, |
| 9665 | 9669 | start: start_row, |
| @@ -9668,10 +9672,10 @@ impl Editor { · 2 unmodified lines | ||
| 9668 | 9672 | reversed: selection.reversed, |
| 9669 | 9673 | }); |
| 9670 | 9674 | |
| 9671 | − if line_count_after > line_count_before { | |
| 9672 | − added_lines += line_count_after - line_count_before; | |
| 9673 | − } else if line_count_before > line_count_after { | |
| 9674 | − removed_lines += line_count_before - line_count_after; | |
| 9675 | + if lines_after > lines_before { | |
| 9676 | + added_lines += lines_after - lines_before; | |
| 9677 | + } else if lines_before > lines_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 | 9723 | pub fn convert_to_upper_case( |
| 9885 | 9724 | &mut self, |
| 9886 | 9725 | _: &ConvertToUpperCase, |
| @@ -21318,13 +21157,6 @@ pub struct LineHighlight { · 11431 unmodified lines | ||
| 21318 | 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 | 21160 | fn render_diff_hunk_controls( |
| 21329 | 21161 | row: u32, |
| 21330 | 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 | +} | |