diff --git a/rope/refactor/extract.py b/rope/refactor/extract.py index 80e74317b..bfd9a7558 100644 --- a/rope/refactor/extract.py +++ b/rope/refactor/extract.py @@ -251,8 +251,15 @@ def _find_matches(self, collector): finder = similarfinder.SimilarFinder(self.info.pymodule) matches = [] for start, end in regions: - matches.extend((finder.get_matches(collector.body_pattern, - collector.checks, start, end))) + region_matches = finder.get_matches(collector.body_pattern, + collector.checks, start, end) + # Don't extract overlapping regions + last_match_end = -1 + for region_match in region_matches: + start, end = region_match.get_region() + if last_match_end < start: + matches.append(region_match) + last_match_end = end collector.matches = matches def _where_to_search(self): diff --git a/ropetest/refactor/extracttest.py b/ropetest/refactor/extracttest.py index 4a346f27a..83681999a 100644 --- a/ropetest/refactor/extracttest.py +++ b/ropetest/refactor/extracttest.py @@ -636,6 +636,27 @@ def test_extract_method_and_similar_sttemnts_return_is_different(self): ' self.attr = self.new_func(p2)\n' self.assertEquals(expected, refactored) + def test_extract_method_and_similar_sttemnts_overlapping_regions(self): + code = 'def func(p):\n' \ + ' a = p\n' \ + ' b = a\n' \ + ' c = b\n' \ + ' d = c\n' \ + ' return d' + start = code.index('a') + end = code.rindex('a') + 1 + refactored = self.do_extract_method( + code, start, end, 'new_func', similar=True) + expected = 'def func(p):\n' \ + ' b = new_func(p)\n' \ + ' d = new_func(b)\n' \ + ' return d\n' \ + 'def new_func(p):\n' \ + ' a = p\n' \ + ' b = a\n' \ + ' return b\n' + self.assertEquals(expected, refactored) + def test_definition_should_appear_where_it_is_visible(self): code = 'if True:\n a = 1\nelse:\n b = 1\n' start = code.rindex('1')