Extract raises IndexError or ModuleSyntaxError instead of RefactoringError for an empty or whitespace-only region

Aberta Para iniciantes
#926 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 7 dias

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
78/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
python

Direção de pesquisa

Comece em _get_single_expression_body() em rope/refactor/extract.py, onde extracted.lstrip()[0] lança IndexError com uma string vazia. Reproduza com o script da issue, que cobre uma região vazia para ExtractVariable e ExtractMethod e uma região apenas com espaços em branco para ExtractMethod. Está pronto quando os três casos lançam RefactoringError com uma mensagem clara, verificado em _ExceptionalConditionChecker.base_conditions() ou após _fix_start() e _fix_end() no construtor.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

ExtractMethod and ExtractVariable raise IndexError for an empty region, and ModuleSyntaxError about a generated wrapper for a region that contains only whitespace. Both are user mistakes, not internal errors, so they should be reported as RefactoringError, as the other bad-region cases are.

This matters for editor integrations. Neovim sends an empty range when the user requests code actions without a selection, so a language server calls extract with an empty region all the time. It has to tell "can't extract here" apart from a real crash it should log.

To Reproduce

import pathlib
import tempfile

from rope.base.project import Project
from rope.refactor import extract

source = "def f(a):\n    b = a + 1\n    return b\n"
root = pathlib.Path(tempfile.mkdtemp())
(root / "m.py").write_text(source)
project = Project(str(root), ropefolder=None)
resource = project.get_resource("m.py")

expr = source.index("a + 1")
indent = source.index("    b =")
for label, cls, start, end in [
    ("extract variable, empty region", extract.ExtractVariable, expr, expr),
    ("extract method, empty region", extract.ExtractMethod, expr, expr),
    ("extract method, whitespace only", extract.ExtractMethod, indent, indent + 4),
]:
    try:
        cls(project, resource, start, end).get_changes("new_name")
    except Exception as e:
        print(f"{label}: {type(e).__name__}: {e}")

Output on master (46ebf37), Python 3.13:

extract variable, empty region: IndexError: string index out of range
extract method, empty region: IndexError: string index out of range
extract method, whitespace only: ModuleSyntaxError: Syntax error in file <string> line <1>: expected an indented block after function definition on line 1

The IndexError comes from _get_single_expression_body(), which indexes extracted.lstrip()[0] on an empty string.

Expected behaviour

RefactoringError, with a message such as "Extracted piece should contain at least one expression or statement". Checking it in _ExceptionalConditionChecker.base_conditions(), or in the constructor after _fix_start() and _fix_end(), would cover both cases.

Editor information

Linguagem predominante
Python
Estrelas
2.2k
Forks
197
Merge médio
2d 13h
PRs com merge (30d)
5

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de python-rope/rope

Todas as issues de python-rope/rope

Issues semelhantes

Mais issues de Python

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.