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());
}
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");
}
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);
}
Aggregations