use of com.intellij.refactoring.extractMethod.PrepareFailedException in project intellij-community by JetBrains.
the class IntroduceParameterHandler method introduceStrategy.
@VisibleForTesting
public boolean introduceStrategy(final Project project, final Editor editor, PsiFile file, final PsiElement[] elements) {
if (elements.length > 0) {
final AbstractInplaceIntroducer inplaceIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor);
if (inplaceIntroducer instanceof InplaceIntroduceParameterPopup) {
return false;
}
final PsiMethod containingMethod = Util.getContainingMethod(elements[0]);
if (containingMethod == null) {
return false;
}
final List<PsiMethod> enclosingMethods = getEnclosingMethods(containingMethod);
if (enclosingMethods.isEmpty()) {
return false;
}
final PsiElement[] elementsCopy;
if (!elements[0].isPhysical()) {
elementsCopy = elements;
} else {
final PsiFile copy = PsiFileFactory.getInstance(project).createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false);
final TextRange range = new TextRange(elements[0].getTextRange().getStartOffset(), elements[elements.length - 1].getTextRange().getEndOffset());
final PsiExpression exprInRange = CodeInsightUtil.findExpressionInRange(copy, range.getStartOffset(), range.getEndOffset());
elementsCopy = exprInRange != null ? new PsiElement[] { exprInRange } : CodeInsightUtil.findStatementsInRange(copy, range.getStartOffset(), range.getEndOffset());
}
final PsiMethod containingMethodCopy = Util.getContainingMethod(elementsCopy[0]);
LOG.assertTrue(containingMethodCopy != null);
final List<PsiMethod> enclosingMethodsInCopy = getEnclosingMethods(containingMethodCopy);
final MyExtractMethodProcessor processor = new MyExtractMethodProcessor(project, editor, elementsCopy, enclosingMethodsInCopy.get(enclosingMethodsInCopy.size() - 1));
try {
if (!processor.prepare())
return false;
processor.showDialog();
//provide context for generated method to check exceptions compatibility
final PsiMethod emptyMethod = JavaPsiFacade.getElementFactory(project).createMethodFromText(processor.generateEmptyMethod("name").getText(), elements[0]);
final Collection<? extends PsiType> types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod);
if (types.isEmpty()) {
return false;
}
if (types.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
final PsiType next = types.iterator().next();
functionalInterfaceSelected(next, enclosingMethods, project, editor, processor, elements);
} else {
final Map<PsiClass, PsiType> classes = new LinkedHashMap<>();
for (PsiType type : types) {
classes.put(PsiUtil.resolveClassInType(type), type);
}
final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
final String methodSignature = PsiFormatUtil.formatMethod(emptyMethod, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_TYPE);
final PsiType returnType = emptyMethod.getReturnType();
LOG.assertTrue(returnType != null);
final String title = "Choose Applicable Functional Interface: " + methodSignature + " -> " + returnType.getPresentableText();
NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), title, new PsiElementProcessor<PsiClass>() {
@Override
public boolean execute(@NotNull PsiClass psiClass) {
functionalInterfaceSelected(classes.get(psiClass), enclosingMethods, project, editor, processor, elements);
return true;
}
}).showInBestPositionFor(editor);
return true;
}
return true;
} catch (IncorrectOperationException | PrepareFailedException ignore) {
}
}
return false;
}
use of com.intellij.refactoring.extractMethod.PrepareFailedException in project intellij-community by JetBrains.
the class ExtractLightMethodObjectHandler method extractLightMethodObject.
@Nullable
public static ExtractedData extractLightMethodObject(final Project project, @Nullable PsiElement originalContext, @NotNull final PsiCodeFragment fragment, final String methodName) throws PrepareFailedException {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiElement[] elements = completeToStatementArray(fragment, elementFactory);
if (elements == null) {
elements = CodeInsightUtil.findStatementsInRange(fragment, 0, fragment.getTextLength());
}
if (elements.length == 0) {
return null;
}
if (originalContext == null) {
return null;
}
PsiFile file = originalContext.getContainingFile();
final PsiFile copy = PsiFileFactory.getInstance(project).createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false);
if (originalContext instanceof PsiKeyword && PsiModifier.PRIVATE.equals(originalContext.getText())) {
final PsiNameIdentifierOwner identifierOwner = PsiTreeUtil.getParentOfType(originalContext, PsiNameIdentifierOwner.class);
if (identifierOwner != null) {
final PsiElement identifier = identifierOwner.getNameIdentifier();
if (identifier != null) {
originalContext = identifier;
}
}
}
final TextRange range = originalContext.getTextRange();
PsiElement originalAnchor = CodeInsightUtil.findElementInRange(copy, range.getStartOffset(), range.getEndOffset(), originalContext.getClass());
if (originalAnchor == null) {
final PsiElement elementAt = copy.findElementAt(range.getStartOffset());
if (elementAt != null && elementAt.getClass() == originalContext.getClass()) {
originalAnchor = PsiTreeUtil.skipSiblingsForward(elementAt, PsiWhiteSpace.class);
}
}
final PsiClass containingClass = PsiTreeUtil.getParentOfType(originalAnchor, PsiClass.class, false);
if (containingClass == null) {
return null;
}
PsiElement anchor = RefactoringUtil.getParentStatement(originalAnchor, false);
if (anchor == null) {
if (PsiTreeUtil.getParentOfType(originalAnchor, PsiCodeBlock.class) != null) {
anchor = originalAnchor;
}
}
final PsiElement container;
if (anchor == null) {
container = ((PsiClassInitializer) containingClass.add(elementFactory.createClassInitializer())).getBody();
anchor = container.getLastChild();
} else {
container = anchor.getParent();
}
final PsiElement firstElementCopy = container.addRangeBefore(elements[0], elements[elements.length - 1], anchor);
final PsiElement[] elementsCopy = CodeInsightUtil.findStatementsInRange(copy, firstElementCopy.getTextRange().getStartOffset(), anchor.getTextRange().getStartOffset());
if (elementsCopy.length == 0) {
return null;
}
if (elementsCopy[elementsCopy.length - 1] instanceof PsiExpressionStatement) {
final PsiExpression expr = ((PsiExpressionStatement) elementsCopy[elementsCopy.length - 1]).getExpression();
if (!(expr instanceof PsiAssignmentExpression)) {
PsiType expressionType = GenericsUtil.getVariableTypeByExpressionType(expr.getType());
if (expressionType instanceof PsiDisjunctionType) {
expressionType = ((PsiDisjunctionType) expressionType).getLeastUpperBound();
}
if (isValidVariableType(expressionType)) {
final String uniqueResultName = JavaCodeStyleManager.getInstance(project).suggestUniqueVariableName("result", elementsCopy[0], true);
final String statementText = expressionType.getCanonicalText() + " " + uniqueResultName + " = " + expr.getText() + ";";
elementsCopy[elementsCopy.length - 1] = elementsCopy[elementsCopy.length - 1].replace(elementFactory.createStatementFromText(statementText, elementsCopy[elementsCopy.length - 1]));
}
}
}
LOG.assertTrue(elementsCopy[0].getParent() == container, "element: " + elementsCopy[0].getText() + "; container: " + container.getText());
final int startOffsetInContainer = elementsCopy[0].getStartOffsetInParent();
final ControlFlow controlFlow;
try {
controlFlow = ControlFlowFactory.getInstance(project).getControlFlow(container, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false, false);
} catch (AnalysisCanceledException e) {
return null;
}
List<PsiVariable> variables = ControlFlowUtil.getUsedVariables(controlFlow, controlFlow.getStartOffset(elementsCopy[0]), controlFlow.getEndOffset(elementsCopy[elementsCopy.length - 1]));
variables = ContainerUtil.filter(variables, variable -> {
PsiElement variableScope = PsiUtil.getVariableCodeBlock(variable, null);
return variableScope != null && PsiTreeUtil.isAncestor(variableScope, elementsCopy[elementsCopy.length - 1], true);
});
final String outputVariables = StringUtil.join(variables, variable -> "\"variable: \" + " + variable.getName(), " +");
PsiStatement outStatement = elementFactory.createStatementFromText("System.out.println(" + outputVariables + ");", anchor);
outStatement = (PsiStatement) container.addAfter(outStatement, elementsCopy[elementsCopy.length - 1]);
copy.accept(new JavaRecursiveElementWalkingVisitor() {
private void makePublic(PsiMember method) {
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
VisibilityUtil.setVisibility(method.getModifierList(), PsiModifier.PUBLIC);
}
}
@Override
public void visitMethod(PsiMethod method) {
super.visitMethod(method);
makePublic(method);
}
@Override
public void visitField(PsiField field) {
super.visitField(field);
makePublic(field);
}
});
final ExtractMethodObjectProcessor extractMethodObjectProcessor = new ExtractMethodObjectProcessor(project, null, elementsCopy, "") {
@Override
protected AbstractExtractDialog createExtractMethodObjectDialog(MyExtractMethodProcessor processor) {
return new LightExtractMethodObjectDialog(this, methodName);
}
@Override
protected boolean isFoldingApplicable() {
return false;
}
};
extractMethodObjectProcessor.getExtractProcessor().setShowErrorDialogs(false);
final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = extractMethodObjectProcessor.getExtractProcessor();
if (extractProcessor.prepare()) {
if (extractProcessor.showDialog()) {
try {
extractProcessor.doExtract();
final UsageInfo[] usages = extractMethodObjectProcessor.findUsages();
extractMethodObjectProcessor.performRefactoring(usages);
extractMethodObjectProcessor.runChangeSignature();
} catch (IncorrectOperationException e) {
LOG.error(e);
}
if (extractMethodObjectProcessor.isCreateInnerClass()) {
extractMethodObjectProcessor.changeInstanceAccess(project);
}
final PsiElement method = extractMethodObjectProcessor.getMethod();
LOG.assertTrue(method != null);
method.delete();
}
} else {
return null;
}
final int startOffset = startOffsetInContainer + container.getTextRange().getStartOffset();
final String generatedCall = copy.getText().substring(startOffset, outStatement.getTextOffset());
return new ExtractedData(generatedCall, (PsiClass) CodeStyleManager.getInstance(project).reformat(extractMethodObjectProcessor.getInnerClass()), originalAnchor);
}
use of com.intellij.refactoring.extractMethod.PrepareFailedException in project intellij-community by JetBrains.
the class TempWithQueryHandler method invokeOnVariable.
private static void invokeOnVariable(final PsiFile file, final Project project, final PsiLocalVariable local, final Editor editor) {
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file))
return;
String localName = local.getName();
final PsiExpression initializer = local.getInitializer();
if (initializer == null) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.has.no.initializer", localName));
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
return;
}
final PsiReference[] refs = ReferencesSearch.search(local, GlobalSearchScope.projectScope(project), false).toArray(PsiReference.EMPTY_ARRAY);
if (refs.length == 0) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.is.never.used", localName));
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
return;
}
final HighlightManager highlightManager = HighlightManager.getInstance(project);
ArrayList<PsiReference> array = new ArrayList<>();
EditorColorsManager manager = EditorColorsManager.getInstance();
final TextAttributes attributes = manager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
for (PsiReference ref : refs) {
PsiElement refElement = ref.getElement();
if (PsiUtil.isAccessedForWriting((PsiExpression) refElement)) {
array.add(ref);
}
if (!array.isEmpty()) {
PsiReference[] refsForWriting = array.toArray(new PsiReference[array.size()]);
highlightManager.addOccurrenceHighlights(editor, refsForWriting, attributes, true, null);
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.is.accessed.for.writing", localName));
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
return;
}
}
final ExtractMethodProcessor processor = new ExtractMethodProcessor(project, editor, new PsiElement[] { initializer }, local.getType(), REFACTORING_NAME, localName, HelpID.REPLACE_TEMP_WITH_QUERY);
try {
if (!processor.prepare())
return;
} catch (PrepareFailedException e) {
CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
ExtractMethodHandler.highlightPrepareError(e, file, editor, project);
return;
}
final PsiClass targetClass = processor.getTargetClass();
if (targetClass != null && targetClass.isInterface()) {
String message = RefactoringBundle.message("cannot.replace.temp.with.query.in.interface");
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
return;
}
if (processor.showDialog()) {
CommandProcessor.getInstance().executeCommand(project, () -> {
final Runnable action = () -> {
try {
processor.doRefactoring();
local.normalizeDeclaration();
PsiExpression initializer1 = local.getInitializer();
PsiExpression[] exprs = new PsiExpression[refs.length];
for (int idx = 0; idx < refs.length; idx++) {
PsiElement ref = refs[idx].getElement();
exprs[idx] = (PsiExpression) ref.replace(initializer1);
}
PsiDeclarationStatement declaration = (PsiDeclarationStatement) local.getParent();
declaration.delete();
highlightManager.addOccurrenceHighlights(editor, exprs, attributes, true, null);
} catch (IncorrectOperationException e) {
LOG.error(e);
}
};
PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(() -> {
ApplicationManager.getApplication().runWriteAction(action);
DuplicatesImpl.processDuplicates(processor, project, editor);
});
}, REFACTORING_NAME, null);
}
WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
}
Aggregations