private static boolean localVariableAreEquivalent( @NotNull PsiLocalVariable var1, @NotNull PsiLocalVariable var2) { final PsiType type1 = var1.getType(); final PsiType type2 = var2.getType(); if (!typesAreEquivalent(type1, type2)) { return false; } final String name1 = var1.getName(); final String name2 = var2.getName(); if (!name1.equals(name2)) { return false; } final PsiExpression initializer1 = var1.getInitializer(); final PsiExpression initializer2 = var2.getInitializer(); return expressionsAreEquivalent(initializer1, initializer2); }
public IntroduceFieldRunnable( boolean rebindNeeded, PsiLocalVariable local, PsiClass aClass, BaseExpressionToFieldHandler.Settings settings, boolean isStatic, PsiExpression[] occurrences) { myVariableName = local.getName(); myFieldName = settings.getFieldName(); myRebindNeeded = rebindNeeded; myLocal = local; myProject = local.getProject(); myDestinationClass = aClass; mySettings = settings; myInitializerPlace = settings.getInitializerPlace(); myOccurences = occurrences; }
private static PsiDeclarationStatement createNewDeclaration( @NotNull PsiLocalVariable variable, PsiExpression initializer) throws IncorrectOperationException { final PsiManager manager = variable.getManager(); final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); final PsiDeclarationStatement newDeclaration = factory.createVariableDeclarationStatement( variable.getName(), variable.getType(), initializer); if (variable.hasModifierProperty(PsiModifier.FINAL)) { final PsiLocalVariable newVariable = (PsiLocalVariable) newDeclaration.getDeclaredElements()[0]; final PsiModifierList modifierList = newVariable.getModifierList(); modifierList.setModifierProperty(PsiModifier.FINAL, true); } return newDeclaration; }
public static boolean containsConflictingDeclarations( PsiCodeBlock block, PsiCodeBlock parentBlock) { final PsiStatement[] statements = block.getStatements(); if (statements.length == 0) { return false; } final List<PsiCodeBlock> followingBlocks = new ArrayList<>(); collectFollowingBlocks(block.getParent().getNextSibling(), followingBlocks); final Project project = block.getProject(); final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); final PsiResolveHelper resolveHelper = facade.getResolveHelper(); for (final PsiStatement statement : statements) { if (!(statement instanceof PsiDeclarationStatement)) { continue; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement) statement; final PsiElement[] variables = declaration.getDeclaredElements(); for (PsiElement variable : variables) { if (!(variable instanceof PsiLocalVariable)) { continue; } final PsiLocalVariable localVariable = (PsiLocalVariable) variable; final String variableName = localVariable.getName(); if (variableName == null) { continue; } final PsiVariable target = resolveHelper.resolveAccessibleReferencedVariable(variableName, parentBlock); if (target instanceof PsiLocalVariable) { return true; } for (PsiCodeBlock codeBlock : followingBlocks) { final PsiVariable target1 = resolveHelper.resolveAccessibleReferencedVariable(variableName, codeBlock); if (target1 instanceof PsiLocalVariable) { return true; } } } } return false; }
@Nullable private static String buildFromOffsetText(PsiExpression expression, PsiLocalVariable variable) throws IncorrectOperationException { expression = ParenthesesUtils.stripParentheses(expression); if (expression == null) { return null; } final String expressionText = expression.getText(); final String variableName = variable.getName(); if (expressionText.equals(variableName)) { final PsiExpression initialValue = variable.getInitializer(); if (initialValue == null) { return null; } return initialValue.getText(); } if (expression instanceof PsiBinaryExpression) { final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) expression; final PsiExpression lhs = binaryExpression.getLOperand(); final PsiExpression rhs = binaryExpression.getROperand(); final String rhsText = buildFromOffsetText(rhs, variable); final PsiJavaToken sign = binaryExpression.getOperationSign(); final IElementType tokenType = sign.getTokenType(); if (ExpressionUtils.isZero(lhs)) { if (tokenType.equals(JavaTokenType.MINUS)) { return '-' + rhsText; } return rhsText; } final String lhsText = buildFromOffsetText(lhs, variable); if (ExpressionUtils.isZero(rhs)) { return lhsText; } return collapseConstant(lhsText + sign.getText() + rhsText, variable); } return collapseConstant(expression.getText(), variable); }
protected void performRefactoring(UsageInfo[] usages) { try { PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); PsiType initializerType = getInitializerType(myForcedType, myParameterInitializer, myLocalVariable); setForcedType(initializerType); // Converting myParameterInitializer if (myParameterInitializer == null) { LOG.assertTrue(myLocalVariable != null); myParameterInitializer = factory.createExpressionFromText(myLocalVariable.getName(), myLocalVariable); } else if (myParameterInitializer instanceof PsiArrayInitializerExpression) { final PsiExpression newExprArrayInitializer = RefactoringUtil.createNewExpressionFromArrayInitializer( (PsiArrayInitializerExpression) myParameterInitializer, initializerType); myParameterInitializer = (PsiExpression) myParameterInitializer.replace(newExprArrayInitializer); } myInitializerWrapper = new JavaExpressionWrapper(myParameterInitializer); // Changing external occurences (the tricky part) IntroduceParameterUtil.processUsages(usages, this); if (myGenerateDelegate) { generateDelegate(myMethodToReplaceIn); if (myMethodToReplaceIn != myMethodToSearchFor) { final PsiMethod method = generateDelegate(myMethodToSearchFor); if (method.getContainingClass().isInterface()) { final PsiCodeBlock block = method.getBody(); if (block != null) { block.delete(); } } } } // Changing signature of initial method // (signature of myMethodToReplaceIn will be either changed now or have already been changed) LOG.assertTrue(initializerType.isValid()); final FieldConflictsResolver fieldConflictsResolver = new FieldConflictsResolver(myParameterName, myMethodToReplaceIn.getBody()); IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts( new UsageInfo(myMethodToReplaceIn), usages, this); if (myMethodToSearchFor != myMethodToReplaceIn) { IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts( new UsageInfo(myMethodToSearchFor), usages, this); } ChangeContextUtil.clearContextInfo(myParameterInitializer); // Replacing expression occurrences for (UsageInfo usage : usages) { if (usage instanceof ChangedMethodCallInfo) { PsiElement element = usage.getElement(); processChangedMethodCall(element); } else if (usage instanceof InternalUsageInfo) { PsiElement element = usage.getElement(); if (element instanceof PsiExpression) { element = RefactoringUtil.outermostParenthesizedExpression((PsiExpression) element); } if (element != null) { if (element.getParent() instanceof PsiExpressionStatement) { element.getParent().delete(); } else { PsiExpression newExpr = factory.createExpressionFromText(myParameterName, element); IntroduceVariableBase.replace((PsiExpression) element, newExpr, myProject); } } } } if (myLocalVariable != null && myRemoveLocalVariable) { myLocalVariable.normalizeDeclaration(); myLocalVariable.getParent().delete(); } fieldConflictsResolver.fix(); } catch (IncorrectOperationException ex) { LOG.error(ex); } }
protected Settings showRefactoringDialog( Project project, final Editor editor, PsiClass parentClass, PsiExpression expr, PsiType type, PsiExpression[] occurrences, PsiElement anchorElement, PsiElement anchorElementIfAll) { final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(expr != null ? expr : anchorElement, PsiMethod.class); PsiLocalVariable localVariable = null; if (expr instanceof PsiReferenceExpression) { PsiElement ref = ((PsiReferenceExpression) expr).resolve(); if (ref instanceof PsiLocalVariable) { localVariable = (PsiLocalVariable) ref; } } else if (anchorElement instanceof PsiLocalVariable) { localVariable = (PsiLocalVariable) anchorElement; } String enteredName = null; boolean replaceAllOccurrences = true; final AbstractInplaceIntroducer activeIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor); if (activeIntroducer != null) { activeIntroducer.stopIntroduce(editor); expr = (PsiExpression) activeIntroducer.getExpr(); localVariable = (PsiLocalVariable) activeIntroducer.getLocalVariable(); occurrences = (PsiExpression[]) activeIntroducer.getOccurrences(); enteredName = activeIntroducer.getInputName(); replaceAllOccurrences = activeIntroducer.isReplaceAllOccurrences(); type = ((InplaceIntroduceConstantPopup) activeIntroducer).getType(); } for (PsiExpression occurrence : occurrences) { if (RefactoringUtil.isAssignmentLHS(occurrence)) { String message = RefactoringBundle.getCannotRefactorMessage("Selected expression is used for write"); CommonRefactoringUtil.showErrorHint( project, editor, message, REFACTORING_NAME, getHelpID()); highlightError(project, editor, occurrence); return null; } } if (localVariable == null) { final PsiElement errorElement = isStaticFinalInitializer(expr); if (errorElement != null) { String message = RefactoringBundle.getCannotRefactorMessage( RefactoringBundle.message("selected.expression.cannot.be.a.constant.initializer")); CommonRefactoringUtil.showErrorHint( project, editor, message, REFACTORING_NAME, getHelpID()); highlightError(project, editor, errorElement); return null; } } else { final PsiExpression initializer = localVariable.getInitializer(); if (initializer == null) { String message = RefactoringBundle.getCannotRefactorMessage( RefactoringBundle.message( "variable.does.not.have.an.initializer", localVariable.getName())); CommonRefactoringUtil.showErrorHint( project, editor, message, REFACTORING_NAME, getHelpID()); return null; } final PsiElement errorElement = isStaticFinalInitializer(initializer); if (errorElement != null) { String message = RefactoringBundle.getCannotRefactorMessage( RefactoringBundle.message( "initializer.for.variable.cannot.be.a.constant.initializer", localVariable.getName())); CommonRefactoringUtil.showErrorHint( project, editor, message, REFACTORING_NAME, getHelpID()); highlightError(project, editor, errorElement); return null; } } final TypeSelectorManagerImpl typeSelectorManager = new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurrences); if (editor != null && editor.getSettings().isVariableInplaceRenameEnabled() && (expr == null || expr.isPhysical()) && activeIntroducer == null) { myInplaceIntroduceConstantPopup = new InplaceIntroduceConstantPopup( project, editor, parentClass, expr, localVariable, occurrences, typeSelectorManager, anchorElement, anchorElementIfAll, expr != null ? createOccurrenceManager(expr, parentClass) : null); if (myInplaceIntroduceConstantPopup.startInplaceIntroduceTemplate()) { return null; } } final IntroduceConstantDialog dialog = new IntroduceConstantDialog( project, parentClass, expr, localVariable, localVariable != null, occurrences, getParentClass(), typeSelectorManager, enteredName); dialog.setReplaceAllOccurrences(replaceAllOccurrences); if (!dialog.showAndGet()) { if (occurrences.length > 1) { WindowManager.getInstance() .getStatusBar(project) .setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting")); } return null; } return new Settings( dialog.getEnteredName(), expr, occurrences, dialog.isReplaceAllOccurrences(), true, true, InitializationPlace.IN_FIELD_DECLARATION, dialog.getFieldVisibility(), localVariable, dialog.getSelectedType(), dialog.isDeleteVariable(), dialog.getDestinationClass(), dialog.isAnnotateAsNonNls(), dialog.introduceEnumConstant()); }
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { LOG.assertTrue(myOutOfScopeVariable != null); PsiManager manager = file.getManager(); myOutOfScopeVariable.normalizeDeclaration(); PsiUtil.setModifierProperty(myOutOfScopeVariable, PsiModifier.FINAL, false); PsiElement commonParent = PsiTreeUtil.findCommonParent(myOutOfScopeVariable, myUnresolvedReference); LOG.assertTrue(commonParent != null); PsiElement child = myOutOfScopeVariable.getTextRange().getStartOffset() < myUnresolvedReference.getTextRange().getStartOffset() ? myOutOfScopeVariable : myUnresolvedReference; while (child.getParent() != commonParent) child = child.getParent(); PsiDeclarationStatement newDeclaration = (PsiDeclarationStatement) JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createStatementFromText("int i = 0", null); PsiVariable variable = (PsiVariable) newDeclaration.getDeclaredElements()[0].replace(myOutOfScopeVariable); if (variable.getInitializer() != null) { variable.getInitializer().delete(); } while (!(child instanceof PsiStatement) || !(child.getParent() instanceof PsiCodeBlock)) { child = child.getParent(); commonParent = commonParent.getParent(); } LOG.assertTrue(commonParent != null); PsiDeclarationStatement added = (PsiDeclarationStatement) commonParent.addBefore(newDeclaration, child); PsiLocalVariable addedVar = (PsiLocalVariable) added.getDeclaredElements()[0]; manager.getCodeStyleManager().reformat(commonParent); // Leave initializer assignment PsiExpression initializer = myOutOfScopeVariable.getInitializer(); if (initializer != null) { PsiExpressionStatement assignment = (PsiExpressionStatement) JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createStatementFromText(myOutOfScopeVariable.getName() + "= e;", null); ((PsiAssignmentExpression) assignment.getExpression()).getRExpression().replace(initializer); assignment = (PsiExpressionStatement) manager.getCodeStyleManager().reformat(assignment); PsiDeclarationStatement declStatement = PsiTreeUtil.getParentOfType(myOutOfScopeVariable, PsiDeclarationStatement.class); LOG.assertTrue(declStatement != null); PsiElement parent = declStatement.getParent(); if (parent instanceof PsiForStatement) { declStatement.replace(assignment); } else { parent.addAfter(assignment, declStatement); } } if (myOutOfScopeVariable.isValid()) { myOutOfScopeVariable.delete(); } if (HighlightControlFlowUtil.checkVariableInitializedBeforeUsage( myUnresolvedReference, addedVar, new THashMap<PsiElement, Collection<PsiReferenceExpression>>()) != null) { initialize(addedVar); } DaemonCodeAnalyzer.getInstance(project).updateVisibleHighlighters(editor); }