Search in sources :

Example 1 with CannotCreateCodeFragmentException

use of com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException in project intellij-community by JetBrains.

the class PyCodeFragmentTest method check.

private void check(final PyFile myFile, final int beginMarker, final int endMarker, final String result) {
    final PsiElement startElement = myFile.findElementAt(beginMarker);
    final PsiElement endElement = myFile.findElementAt(endMarker - BEGIN_MARKER.length());
    PsiElement context = PsiTreeUtil.findCommonParent(startElement, endElement);
    if (!(context instanceof ScopeOwner)) {
        context = PsiTreeUtil.getParentOfType(context, ScopeOwner.class);
    }
    final StringBuffer buffer = new StringBuffer();
    try {
        final CodeFragment fragment = PyCodeFragmentUtil.createCodeFragment((ScopeOwner) context, startElement, endElement);
        if (fragment.isReturnInstructionInside()) {
            buffer.append("Return instruction inside found").append("\n");
        }
        buffer.append("In:\n");
        for (String inputVariable : new TreeSet<>(fragment.getInputVariables())) {
            buffer.append(inputVariable).append('\n');
        }
        buffer.append("Out:\n");
        for (String outputVariable : new TreeSet<>(fragment.getOutputVariables())) {
            buffer.append(outputVariable).append('\n');
        }
    } catch (CannotCreateCodeFragmentException e) {
        assertEquals(result.trim(), e.getMessage());
        return;
    }
    assertEquals(result.trim(), buffer.toString().trim());
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) CannotCreateCodeFragmentException(com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException) TreeSet(java.util.TreeSet) CodeFragment(com.intellij.codeInsight.codeFragment.CodeFragment) PsiElement(com.intellij.psi.PsiElement)

Example 2 with CannotCreateCodeFragmentException

use of com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException in project intellij-community by JetBrains.

the class PyExtractMethodHandler method invokeOnEditor.

private static void invokeOnEditor(final Project project, final Editor editor, final PsiFile file) {
    CommonRefactoringUtil.checkReadOnlyStatus(project, file);
    PsiElement element1 = null;
    PsiElement element2 = null;
    final SelectionModel selectionModel = editor.getSelectionModel();
    if (selectionModel.hasSelection()) {
        element1 = file.findElementAt(selectionModel.getSelectionStart());
        element2 = file.findElementAt(selectionModel.getSelectionEnd() - 1);
    } else {
        final CaretModel caretModel = editor.getCaretModel();
        final Document document = editor.getDocument();
        int lineNumber = document.getLineNumber(caretModel.getOffset());
        if ((lineNumber >= 0) && (lineNumber < document.getLineCount())) {
            element1 = file.findElementAt(document.getLineStartOffset(lineNumber));
            element2 = file.findElementAt(document.getLineEndOffset(lineNumber) - 1);
        }
    }
    // Pass comments and whitespaces
    element1 = PyPsiUtils.getNextSignificantLeaf(element1, false);
    element2 = PyPsiUtils.getPrevSignificantLeaf(element2, false);
    if (element1 == null || element2 == null) {
        CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.extract.method.error.bad.selection"), RefactoringBundle.message("extract.method.title"), "refactoring.extractMethod");
        return;
    }
    if (rangeBelongsToSameClassBody(element1, element2)) {
        CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.extract.method.error.class.level"), RefactoringBundle.message("extract.method.title"), "refactoring.extractMethod");
        return;
    }
    final Couple<PsiElement> statements = getStatementsRange(element1, element2);
    if (statements != null) {
        final ScopeOwner owner = PsiTreeUtil.getParentOfType(statements.getFirst(), ScopeOwner.class);
        if (owner == null) {
            return;
        }
        final PyCodeFragment fragment;
        try {
            fragment = PyCodeFragmentUtil.createCodeFragment(owner, element1, element2);
        } catch (CannotCreateCodeFragmentException e) {
            CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), RefactoringBundle.message("extract.method.title"), "refactoring.extractMethod");
            return;
        }
        PyExtractMethodUtil.extractFromStatements(project, editor, fragment, statements.getFirst(), statements.getSecond());
        return;
    }
    final PsiElement expression = PyRefactoringUtil.getSelectedExpression(project, file, element1, element2);
    if (expression != null) {
        final ScopeOwner owner = PsiTreeUtil.getParentOfType(element1, ScopeOwner.class);
        if (owner == null) {
            return;
        }
        final PyCodeFragment fragment;
        try {
            fragment = PyCodeFragmentUtil.createCodeFragment(owner, element1, element2);
        } catch (CannotCreateCodeFragmentException e) {
            CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), RefactoringBundle.message("extract.method.title"), "refactoring.extractMethod");
            return;
        }
        PyExtractMethodUtil.extractFromExpression(project, editor, fragment, expression);
        return;
    }
    CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.extract.method.error.bad.selection"), RefactoringBundle.message("extract.method.title"), "refactoring.extractMethod");
}
Also used : ScopeOwner(com.jetbrains.python.codeInsight.controlflow.ScopeOwner) PyCodeFragment(com.jetbrains.python.codeInsight.codeFragment.PyCodeFragment) CannotCreateCodeFragmentException(com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException) PsiElement(com.intellij.psi.PsiElement)

Example 3 with CannotCreateCodeFragmentException

use of com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException in project intellij-community by JetBrains.

the class PyCodeFragmentUtil method createCodeFragment.

@NotNull
public static PyCodeFragment createCodeFragment(@NotNull final ScopeOwner owner, @NotNull final PsiElement startInScope, @NotNull final PsiElement endInScope) throws CannotCreateCodeFragmentException {
    final int start = startInScope.getTextOffset();
    final int end = endInScope.getTextOffset() + endInScope.getTextLength();
    final ControlFlow flow = ControlFlowCache.getControlFlow(owner);
    if (flow == null) {
        throw new CannotCreateCodeFragmentException(PyBundle.message("refactoring.extract.method.error.undetermined.execution.flow"));
    }
    final List<Instruction> graph = Arrays.asList(flow.getInstructions());
    final List<Instruction> subGraph = getFragmentSubGraph(graph, start, end);
    final AnalysisResult subGraphAnalysis = analyseSubGraph(subGraph, start, end);
    if ((subGraphAnalysis.regularExits > 0 && subGraphAnalysis.returns > 0) || subGraphAnalysis.targetInstructions > 1 || subGraphAnalysis.outerLoopBreaks > 0) {
        throw new CannotCreateCodeFragmentException(PyBundle.message("refactoring.extract.method.error.interrupted.execution.flow"));
    }
    if (subGraphAnalysis.starImports > 0) {
        throw new CannotCreateCodeFragmentException(PyBundle.message("refactoring.extract.method.error.star.import"));
    }
    final Set<String> globalWrites = getGlobalWrites(subGraph, owner);
    final Set<String> nonlocalWrites = getNonlocalWrites(subGraph, owner);
    final Set<String> inputNames = new HashSet<>();
    for (PsiElement element : filterElementsInScope(getInputElements(subGraph, graph), owner)) {
        final String name = getName(element);
        if (name != null) {
            // Ignore "self" and "cls", they are generated automatically when extracting any method fragment
            if (resolvesToBoundMethodParameter(element)) {
                continue;
            }
            if (globalWrites.contains(name) || nonlocalWrites.contains(name)) {
                continue;
            }
            inputNames.add(name);
        }
    }
    final Set<String> outputNames = new HashSet<>();
    for (PsiElement element : getOutputElements(subGraph, graph)) {
        final String name = getName(element);
        if (name != null) {
            if (globalWrites.contains(name) || nonlocalWrites.contains(name)) {
                continue;
            }
            outputNames.add(name);
        }
    }
    final boolean yieldsFound = subGraphAnalysis.yieldExpressions > 0;
    if (yieldsFound && LanguageLevel.forElement(owner).isOlderThan(LanguageLevel.PYTHON33)) {
        throw new CannotCreateCodeFragmentException(PyBundle.message("refactoring.extract.method.error.yield"));
    }
    final boolean isAsync = owner instanceof PyFunction && ((PyFunction) owner).isAsync();
    return new PyCodeFragment(inputNames, outputNames, globalWrites, nonlocalWrites, subGraphAnalysis.returns > 0, yieldsFound, isAsync);
}
Also used : CannotCreateCodeFragmentException(com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException) ReadWriteInstruction(com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction) Instruction(com.intellij.codeInsight.controlflow.Instruction) ControlFlow(com.intellij.codeInsight.controlflow.ControlFlow) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

CannotCreateCodeFragmentException (com.intellij.codeInsight.codeFragment.CannotCreateCodeFragmentException)3 PsiElement (com.intellij.psi.PsiElement)2 ScopeOwner (com.jetbrains.python.codeInsight.controlflow.ScopeOwner)2 CodeFragment (com.intellij.codeInsight.codeFragment.CodeFragment)1 ControlFlow (com.intellij.codeInsight.controlflow.ControlFlow)1 Instruction (com.intellij.codeInsight.controlflow.Instruction)1 PyCodeFragment (com.jetbrains.python.codeInsight.codeFragment.PyCodeFragment)1 ReadWriteInstruction (com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction)1 TreeSet (java.util.TreeSet)1 NotNull (org.jetbrains.annotations.NotNull)1