@NotNull private static PsiElement[] extractReferencedVariables(@NotNull PsiTypeElement typeElement) { final PsiElement parent = typeElement.getParent(); if (parent instanceof PsiVariable) { if (parent instanceof PsiField) { PsiField aField = (PsiField) parent; List<PsiField> fields = new ArrayList<>(); while (true) { fields.add(aField); aField = PsiTreeUtil.getNextSiblingOfType(aField, PsiField.class); if (aField == null || aField.getTypeElement() != typeElement) { return fields.toArray(new PsiElement[fields.size()]); } } } else if (parent instanceof PsiLocalVariable) { final PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(parent, PsiDeclarationStatement.class); if (declaration != null) { return Arrays.stream(declaration.getDeclaredElements()) .filter(PsiVariable.class::isInstance) .toArray(PsiVariable[]::new); } } return new PsiElement[] {parent}; } else { return PsiElement.EMPTY_ARRAY; } }
private static boolean declarationStatementsAreEquivalent( @NotNull PsiDeclarationStatement statement1, @NotNull PsiDeclarationStatement statement2) { final PsiElement[] elements1 = statement1.getDeclaredElements(); final List<PsiLocalVariable> vars1 = new ArrayList<PsiLocalVariable>(elements1.length); for (PsiElement anElement : elements1) { if (anElement instanceof PsiLocalVariable) { vars1.add((PsiLocalVariable) anElement); } } final PsiElement[] elements2 = statement2.getDeclaredElements(); final List<PsiLocalVariable> vars2 = new ArrayList<PsiLocalVariable>(elements2.length); for (PsiElement anElement : elements2) { if (anElement instanceof PsiLocalVariable) { vars2.add((PsiLocalVariable) anElement); } } final int size = vars1.size(); if (size != vars2.size()) { return false; } for (int i = 0; i < size; i++) { final PsiLocalVariable var1 = vars1.get(i); final PsiLocalVariable var2 = vars2.get(i); if (!localVariablesAreEquivalent(var1, var2)) { return false; } } return true; }
public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException { final PsiLocalVariable variable = (PsiLocalVariable) element; final PsiReference[] references = ReferencesSearch.search(variable, variable.getUseScope(), false) .toArray(PsiReference.EMPTY_ARRAY); final PsiCodeBlock tightestBlock = MoveDeclarationPredicate.getTightestBlock(references); assert tightestBlock != null; final PsiDeclarationStatement declaration = (PsiDeclarationStatement) variable.getParent(); final PsiReference firstReference = references[0]; final PsiElement referenceElement = firstReference.getElement(); PsiDeclarationStatement newDeclaration; if (tightestBlock.equals(PsiTreeUtil.getParentOfType(referenceElement, PsiCodeBlock.class))) { // containing block of first reference is the same as the common // block of all. newDeclaration = moveDeclarationToReference(referenceElement, variable, tightestBlock); } else { // declaration must be moved to common block (first reference block // is too deep) final PsiElement child = MoveDeclarationPredicate.getChildWhichContainsElement(tightestBlock, referenceElement); newDeclaration = createNewDeclaration(variable, null); newDeclaration = (PsiDeclarationStatement) tightestBlock.addBefore(newDeclaration, child); } assert declaration != null; if (declaration.getDeclaredElements().length == 1) { declaration.delete(); } else { variable.delete(); } highlightElement(newDeclaration); }
@NotNull @Override public PsiDeclarationStatement createVariableDeclarationStatement( @NotNull String name, @NotNull PsiType type, @Nullable PsiExpression initializer) throws IncorrectOperationException { if (!isIdentifier(name)) { throw new IncorrectOperationException("\"" + name + "\" is not an identifier."); } if (PsiType.NULL.equals(type)) { throw new IncorrectOperationException("Cannot create variable with type \"null\"."); } String text = "X " + name + (initializer != null ? " = x" : "") + ";"; PsiDeclarationStatement statement = (PsiDeclarationStatement) createStatementFromText(text, null); PsiVariable variable = (PsiVariable) statement.getDeclaredElements()[0]; replace(variable.getTypeElement(), createTypeElement(type), text); boolean generateFinalLocals = JavaCodeStyleSettingsFacade.getInstance(myManager.getProject()).isGenerateFinalLocals(); PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, generateFinalLocals); if (initializer != null) { replace(variable.getInitializer(), initializer, text); } GeneratedMarkerVisitor.markGenerated(statement); return statement; }
private static boolean isIndexedListLoopStatement(PsiForStatement forStatement, boolean ignoreUntypedCollections) { final PsiStatement initialization = forStatement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return false; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement)initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); final PsiElement secondDeclaredElement; if (declaredElements.length == 1) { secondDeclaredElement = null; } else if (declaredElements.length == 2) { secondDeclaredElement = declaredElements[1]; } else { return false; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return false; } final PsiVariable indexVariable = (PsiVariable)declaredElement; final PsiExpression initialValue = indexVariable.getInitializer(); if (initialValue == null) { return false; } final Object constant = ExpressionUtils.computeConstantExpression(initialValue); if (!(constant instanceof Number)) { return false; } final Number number = (Number)constant; if (number.intValue() != 0) { return false; } final PsiExpression condition = forStatement.getCondition(); final Holder collectionHolder = getCollectionFromSizeComparison(condition, indexVariable, secondDeclaredElement); if (collectionHolder == null) { return false; } final PsiStatement update = forStatement.getUpdate(); if (!VariableAccessUtils.variableIsIncremented(indexVariable, update)) { return false; } final PsiStatement body = forStatement.getBody(); if (!isIndexVariableOnlyUsedAsListIndex(collectionHolder, indexVariable, body)) { return false; } if (collectionHolder != Holder.DUMMY) { final PsiVariable collection = collectionHolder.getVariable(); final PsiClassType collectionType = (PsiClassType)collection.getType(); final PsiType[] parameters = collectionType.getParameters(); if (ignoreUntypedCollections && parameters.length == 0) { return false; } return !VariableAccessUtils.variableIsAssigned(collection, body); } return true; }
static boolean isArrayLoopStatement(PsiForStatement forStatement) { final PsiStatement initialization = forStatement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return false; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement)initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); final PsiElement secondDeclaredElement; if (declaredElements.length == 1) { secondDeclaredElement = null; } else if (declaredElements.length == 2) { secondDeclaredElement = declaredElements[1]; } else { return false; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return false; } final PsiVariable indexVariable = (PsiVariable)declaredElement; final PsiExpression initialValue = indexVariable.getInitializer(); if (initialValue == null) { return false; } final Object constant = ExpressionUtils.computeConstantExpression(initialValue); if (!(constant instanceof Integer)) { return false; } final Integer integer = (Integer)constant; if (integer.intValue() != 0) { return false; } final PsiStatement update = forStatement.getUpdate(); if (!VariableAccessUtils.variableIsIncremented(indexVariable, update)) { return false; } final PsiExpression condition = forStatement.getCondition(); final PsiReferenceExpression arrayReference = getVariableReferenceFromCondition(condition, indexVariable, secondDeclaredElement); if (arrayReference == null) { return false; } final PsiElement element = arrayReference.resolve(); if (!(element instanceof PsiVariable)) { return false; } final PsiVariable arrayVariable = (PsiVariable)element; final PsiStatement body = forStatement.getBody(); return body == null || isIndexVariableOnlyUsedAsIndex(arrayVariable, indexVariable, body) && !VariableAccessUtils.variableIsAssigned(arrayVariable, body) && !VariableAccessUtils.arrayContentsAreAssigned(arrayVariable, body); }
private static ElementToWorkOn getElementToWorkOn( final Editor editor, final PsiFile file, final String refactoringName, final String helpId, final Project project, PsiLocalVariable localVar, PsiExpression expr) { int startOffset = 0; int endOffset = 0; if (localVar == null && expr == null) { startOffset = editor.getSelectionModel().getSelectionStart(); endOffset = editor.getSelectionModel().getSelectionEnd(); expr = CodeInsightUtil.findExpressionInRange(file, startOffset, endOffset); if (expr == null) { PsiIdentifier ident = CodeInsightUtil.findElementInRange(file, startOffset, endOffset, PsiIdentifier.class); if (ident != null) { localVar = PsiTreeUtil.getParentOfType(ident, PsiLocalVariable.class); } } } if (expr == null && localVar == null) { PsiElement[] statements = CodeInsightUtil.findStatementsInRange(file, startOffset, endOffset); if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) { expr = ((PsiExpressionStatement) statements[0]).getExpression(); } else if (statements.length == 1 && statements[0] instanceof PsiDeclarationStatement) { PsiDeclarationStatement decl = (PsiDeclarationStatement) statements[0]; PsiElement[] declaredElements = decl.getDeclaredElements(); if (declaredElements.length == 1 && declaredElements[0] instanceof PsiLocalVariable) { localVar = (PsiLocalVariable) declaredElements[0]; } } } if (localVar == null && expr == null) { expr = IntroduceVariableBase.getSelectedExpression(project, file, startOffset, endOffset); } if (localVar == null && expr == null) { String message = RefactoringBundle.getCannotRefactorMessage( RefactoringBundle.message("error.wrong.caret.position.local.or.expression.name")); CommonRefactoringUtil.showErrorHint(project, editor, message, refactoringName, helpId); return null; } return new ElementToWorkOn(localVar, expr); }
private void copyToFinal() throws IncorrectOperationException { PsiManager psiManager = myClass.getManager(); PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory(); PsiExpression initializer = factory.createExpressionFromText(myVariable.getName(), myClass); String newName = suggestNewName(psiManager.getProject(), myVariable); PsiType type = myVariable.getType(); PsiDeclarationStatement copyDecl = factory.createVariableDeclarationStatement(newName, type, initializer); PsiVariable newVariable = (PsiVariable) copyDecl.getDeclaredElements()[0]; PsiUtil.setModifierProperty(newVariable, PsiModifier.FINAL, true); PsiElement statement = getStatementToInsertBefore(); if (statement == null) return; statement.getParent().addBefore(copyDecl, statement); PsiExpression newExpression = factory.createExpressionFromText(newName, myVariable); replaceReferences(myClass, myVariable, newExpression); }
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; }
@Override public void visitForStatement(@NotNull PsiForStatement statement) { super.visitForStatement(statement); final PsiStatement initialization = statement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); if (declaredElements.length != 1) { return; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiLocalVariable)) { return; } final PsiLocalVariable variable = (PsiLocalVariable) declaredElement; final PsiExpression initialValue = variable.getInitializer(); if (initialValue == null) { return; } final PsiExpression condition = statement.getCondition(); if (!ExpressionUtils.isVariableLessThanComparison(condition, variable)) { return; } final PsiStatement update = statement.getUpdate(); if (!VariableAccessUtils.variableIsIncremented(variable, update)) { return; } final PsiArrayAccessExpression arrayAccessExpression = getArrayAccessExpression(statement); if (arrayAccessExpression == null) { return; } final PsiExpression arrayExpression = arrayAccessExpression.getArrayExpression(); final PsiType type = arrayExpression.getType(); if (!(type instanceof PsiArrayType) || type.getDeepComponentType() instanceof PsiPrimitiveType) { return; } final PsiStatement body = statement.getBody(); if (!bodyIsArrayToCollectionCopy(body, variable, true)) { return; } registerStatementError(statement); }
private boolean isIteratorNextDeclaration( PsiStatement statement, String iteratorName, PsiType contentType) { if (!(statement instanceof PsiDeclarationStatement)) { return false; } final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) statement; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); if (declaredElements.length != 1) { return false; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return false; } final PsiVariable variable = (PsiVariable) declaredElement; final PsiExpression initializer = variable.getInitializer(); return isIteratorNext(initializer, iteratorName, contentType); }
private boolean isArrayElementDeclaration( PsiStatement statement, PsiVariable arrayVariable, String indexName) { if (!(statement instanceof PsiDeclarationStatement)) { return false; } final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) statement; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); if (declaredElements.length != 1) { return false; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return false; } final PsiVariable variable = (PsiVariable) declaredElement; final PsiExpression initializer = variable.getInitializer(); return isArrayLookup(initializer, indexName, arrayVariable); }
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; }
private boolean isListElementDeclaration( PsiStatement statement, PsiVariable listVariable, String indexName, PsiType type) { if (!(statement instanceof PsiDeclarationStatement)) { return false; } final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) statement; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); if (declaredElements.length != 1) { return false; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return false; } final PsiVariable variable = (PsiVariable) declaredElement; final PsiExpression initializer = variable.getInitializer(); if (!isListGetLookup(initializer, indexName, listVariable)) { return false; } return type != null && type.equals(variable.getType()); }
private static PsiArrayAccessExpression getArrayAccessExpression(PsiForStatement forStatement) { final PsiStatement body = getBody(forStatement); if (body == null) { return null; } final PsiExpression arrayAccessExpression; if (body instanceof PsiExpressionStatement) { final PsiExpressionStatement expressionStatement = (PsiExpressionStatement) body; final PsiExpression expression = expressionStatement.getExpression(); if (!(expression instanceof PsiMethodCallExpression)) { return null; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) expression; final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); PsiExpression[] expressions = argumentList.getExpressions(); arrayAccessExpression = expressions.length == 0 ? null : expressions[0]; } else if (body instanceof PsiDeclarationStatement) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) body; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); if (declaredElements.length != 1) { return null; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; arrayAccessExpression = variable.getInitializer(); } else { return null; } final PsiExpression deparenthesizedArgument = ParenthesesUtils.stripParentheses(arrayAccessExpression); if (!(deparenthesizedArgument instanceof PsiArrayAccessExpression)) { return null; } return (PsiArrayAccessExpression) deparenthesizedArgument; }
private static boolean bodyIsArrayToCollectionCopy( PsiStatement body, PsiVariable variable, boolean shouldBeOffsetArrayAccess) { if (body instanceof PsiExpressionStatement) { final PsiExpressionStatement expressionStatement = (PsiExpressionStatement) body; final PsiExpression expression = expressionStatement.getExpression(); return expressionIsArrayToCollectionCopy(expression, variable, shouldBeOffsetArrayAccess); } else if (body instanceof PsiBlockStatement) { final PsiBlockStatement blockStatement = (PsiBlockStatement) body; final PsiCodeBlock codeBlock = blockStatement.getCodeBlock(); final PsiStatement[] statements = codeBlock.getStatements(); if (statements.length == 1) { return bodyIsArrayToCollectionCopy(statements[0], variable, shouldBeOffsetArrayAccess); } else if (statements.length == 2) { final PsiStatement statement = statements[0]; if (!(statement instanceof PsiDeclarationStatement)) { return false; } final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) statement; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); if (declaredElements.length != 1) { return false; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return false; } final PsiVariable localVariable = (PsiVariable) declaredElement; final PsiExpression initializer = localVariable.getInitializer(); if (!ExpressionUtils.isOffsetArrayAccess(initializer, variable)) { return false; } return bodyIsArrayToCollectionCopy(statements[1], localVariable, false); } } return false; }
private void makeArray(PsiVariable variable) throws IncorrectOperationException { PsiType type = variable.getType(); PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory(); PsiType newType = type.createArrayType(); PsiDeclarationStatement variableDeclarationStatement; PsiExpression initializer = variable.getInitializer(); if (initializer == null) { String expression = "[1]"; while (type instanceof PsiArrayType) { expression += "[1]"; type = ((PsiArrayType) type).getComponentType(); } PsiExpression init = factory.createExpressionFromText("new " + type.getCanonicalText() + expression, variable); variableDeclarationStatement = factory.createVariableDeclarationStatement(variable.getName(), newType, init); } else { PsiExpression init = factory.createExpressionFromText("{ " + initializer.getText() + " }", variable); variableDeclarationStatement = factory.createVariableDeclarationStatement(variable.getName(), newType, init); } PsiVariable newVariable = (PsiVariable) variableDeclarationStatement.getDeclaredElements()[0]; PsiUtil.setModifierProperty(newVariable, PsiModifier.FINAL, true); PsiElement newExpression = factory.createExpressionFromText(variable.getName() + "[0]", variable); PsiElement outerCodeBlock = PsiUtil.getVariableCodeBlock(variable, null); if (outerCodeBlock == null) return; List<PsiReferenceExpression> outerReferences = new ArrayList<PsiReferenceExpression>(); collectReferences(outerCodeBlock, variable, outerReferences); replaceReferences(outerReferences, newExpression); variable.replace(newVariable); }
private static boolean updateUsesInitializer(PsiForStatement statement) { final PsiStatement initialization = statement.getInitialization(); final PsiStatement update = statement.getUpdate(); if (initialization == null) { return true; } if (update == null) { return true; } if (!(initialization instanceof PsiDeclarationStatement)) { return true; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); if (declaredElements.length != 1) { return true; } if (declaredElements[0] == null || !(declaredElements[0] instanceof PsiLocalVariable)) { return true; } final PsiLocalVariable localVar = (PsiLocalVariable) declaredElements[0]; return statementUsesVariable(update, localVar); }
@Nullable private String createArrayIterationText(@NotNull PsiForStatement forStatement) { final PsiExpression condition = forStatement.getCondition(); final PsiBinaryExpression strippedCondition = (PsiBinaryExpression) ParenthesesUtils.stripParentheses(condition); if (strippedCondition == null) { return null; } final PsiExpression lhs = ParenthesesUtils.stripParentheses(strippedCondition.getLOperand()); if (lhs == null) { return null; } final PsiExpression rhs = ParenthesesUtils.stripParentheses(strippedCondition.getROperand()); if (rhs == null) { return null; } final IElementType tokenType = strippedCondition.getOperationTokenType(); final PsiReferenceExpression arrayLengthExpression; final String indexName; if (tokenType.equals(JavaTokenType.LT)) { arrayLengthExpression = (PsiReferenceExpression) ParenthesesUtils.stripParentheses(rhs); indexName = lhs.getText(); } else if (tokenType.equals(JavaTokenType.GT)) { arrayLengthExpression = (PsiReferenceExpression) ParenthesesUtils.stripParentheses(lhs); indexName = rhs.getText(); } else { return null; } if (arrayLengthExpression == null) { return null; } PsiReferenceExpression arrayReference = (PsiReferenceExpression) arrayLengthExpression.getQualifierExpression(); if (arrayReference == null) { final PsiElement target = arrayLengthExpression.resolve(); if (!(target instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) target; final PsiExpression initializer = variable.getInitializer(); if (!(initializer instanceof PsiReferenceExpression)) { return null; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) initializer; arrayReference = (PsiReferenceExpression) referenceExpression.getQualifierExpression(); if (arrayReference == null) { return null; } } final PsiType type = arrayReference.getType(); if (!(type instanceof PsiArrayType)) { return null; } final PsiArrayType arrayType = (PsiArrayType) type; final PsiType componentType = arrayType.getComponentType(); final String typeText = componentType.getCanonicalText(); final PsiElement target = arrayReference.resolve(); if (!(target instanceof PsiVariable)) { return null; } final PsiVariable arrayVariable = (PsiVariable) target; final PsiStatement body = forStatement.getBody(); final PsiStatement firstStatement = getFirstStatement(body); final boolean isDeclaration = isArrayElementDeclaration(firstStatement, arrayVariable, indexName); final String contentVariableName; @NonNls final String finalString; final PsiStatement statementToSkip; if (isDeclaration) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) firstStatement; assert declarationStatement != null; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; if (VariableAccessUtils.variableIsAssigned(variable, forStatement)) { final String collectionName = arrayReference.getReferenceName(); contentVariableName = createNewVariableName(forStatement, componentType, collectionName); final Project project = forStatement.getProject(); final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (codeStyleSettings.GENERATE_FINAL_LOCALS) { finalString = "final "; } else { finalString = ""; } statementToSkip = null; } else { contentVariableName = variable.getName(); statementToSkip = declarationStatement; if (variable.hasModifierProperty(PsiModifier.FINAL)) { finalString = "final "; } else { finalString = ""; } } } else { final String collectionName = arrayReference.getReferenceName(); contentVariableName = createNewVariableName(forStatement, componentType, collectionName); final Project project = forStatement.getProject(); final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (codeStyleSettings.GENERATE_FINAL_LOCALS) { finalString = "final "; } else { finalString = ""; } statementToSkip = null; } @NonNls final StringBuilder out = new StringBuilder(); out.append("for("); out.append(finalString); out.append(typeText); out.append(' '); out.append(contentVariableName); out.append(": "); final String arrayName = arrayReference.getText(); out.append(arrayName); out.append(')'); if (body != null) { replaceArrayAccess( body, contentVariableName, arrayVariable, indexName, statementToSkip, out); } return out.toString(); }
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { if (!myField.isValid()) return; // weird. should not get here when field becomes invalid final Collection<PsiReference> refs = ReferencesSearch.search(myField).findAll(); if (refs.isEmpty()) return; Set<PsiReference> refsSet = new HashSet<PsiReference>(refs); PsiCodeBlock anchorBlock = findAnchorBlock(refs); if (anchorBlock == null) return; // was assert, but need to fix the case when obsolete inspection highlighting is // left if (!CodeInsightUtil.preparePsiElementsForWrite(anchorBlock)) return; final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project); final String propertyName = styleManager.variableNameToPropertyName(myField.getName(), VariableKind.FIELD); String localName = styleManager.propertyNameToVariableName(propertyName, VariableKind.LOCAL_VARIABLE); localName = RefactoringUtil.suggestUniqueVariableName(localName, anchorBlock, myField); PsiElement firstElement = getFirstElement(refs); boolean mayBeFinal = mayBeFinal(refsSet, firstElement); PsiElement newDeclaration = null; try { final PsiElement anchor = getAnchorElement(anchorBlock, firstElement); if (anchor instanceof PsiExpressionStatement && ((PsiExpressionStatement) anchor).getExpression() instanceof PsiAssignmentExpression) { final PsiAssignmentExpression expression = (PsiAssignmentExpression) ((PsiExpressionStatement) anchor).getExpression(); if (expression.getOperationTokenType() == JavaTokenType.EQ && expression.getLExpression() instanceof PsiReferenceExpression && ((PsiReference) expression.getLExpression()).isReferenceTo(myField)) { final PsiExpression initializer = expression.getRExpression(); final PsiDeclarationStatement decl = elementFactory.createVariableDeclarationStatement( localName, myField.getType(), initializer); if (!mayBeFinal) { PsiUtil.setModifierProperty( ((PsiModifierListOwner) decl.getDeclaredElements()[0]), PsiModifier.FINAL, false); } newDeclaration = anchor.replace(decl); refsSet.remove(expression.getLExpression()); retargetReferences(elementFactory, localName, refsSet); } else { newDeclaration = addDeclarationWithFieldInitializerAndRetargetReferences( elementFactory, localName, anchorBlock, anchor, refsSet); } } else { newDeclaration = addDeclarationWithFieldInitializerAndRetargetReferences( elementFactory, localName, anchorBlock, anchor, refsSet); } } catch (IncorrectOperationException e) { LOG.error(e); } if (newDeclaration != null) { final PsiFile psiFile = myField.getContainingFile(); final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); if (editor != null && IJSwingUtilities.hasFocus(editor.getComponent())) { final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); if (file == psiFile) { editor.getCaretModel().moveToOffset(newDeclaration.getTextOffset()); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } } } try { myField.normalizeDeclaration(); myField.delete(); } catch (IncorrectOperationException e) { LOG.error(e); } }
@Override public void visitDeclarationStatement(PsiDeclarationStatement statement) { for (PsiElement element : statement.getDeclaredElements()) { element.acceptChildren(this); } }
@Nullable private String createListIterationText(@NotNull PsiForStatement forStatement) { final PsiBinaryExpression condition = (PsiBinaryExpression) ParenthesesUtils.stripParentheses(forStatement.getCondition()); if (condition == null) { return null; } final PsiExpression lhs = ParenthesesUtils.stripParentheses(condition.getLOperand()); if (lhs == null) { return null; } final PsiExpression rhs = ParenthesesUtils.stripParentheses(condition.getROperand()); if (rhs == null) { return null; } final IElementType tokenType = condition.getOperationTokenType(); final String indexName; PsiExpression collectionSize; if (JavaTokenType.LT.equals(tokenType)) { indexName = lhs.getText(); collectionSize = rhs; } else if (JavaTokenType.GT.equals(tokenType)) { indexName = rhs.getText(); collectionSize = lhs; } else { return null; } if (collectionSize instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) collectionSize; final PsiElement target = referenceExpression.resolve(); if (target instanceof PsiVariable) { final PsiVariable variable = (PsiVariable) target; collectionSize = ParenthesesUtils.stripParentheses(variable.getInitializer()); } } if (!(collectionSize instanceof PsiMethodCallExpression)) { return null; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) ParenthesesUtils.stripParentheses(collectionSize); if (methodCallExpression == null) { return null; } final PsiReferenceExpression listLengthExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifier = ParenthesesUtils.stripParentheses(listLengthExpression.getQualifierExpression()); final PsiReferenceExpression listReference; if (qualifier instanceof PsiReferenceExpression) { listReference = (PsiReferenceExpression) qualifier; } else { listReference = null; } PsiType parameterType; if (listReference == null) { parameterType = extractListTypeFromContainingClass(forStatement); } else { final PsiType type = listReference.getType(); if (type == null) { return null; } parameterType = extractContentTypeFromType(type); } if (parameterType == null) { parameterType = TypeUtils.getObjectType(forStatement); } final String typeString = parameterType.getCanonicalText(); final PsiVariable listVariable; if (listReference == null) { listVariable = null; } else { final PsiElement target = listReference.resolve(); if (!(target instanceof PsiVariable)) { return null; } listVariable = (PsiVariable) target; } final PsiStatement body = forStatement.getBody(); final PsiStatement firstStatement = getFirstStatement(body); final boolean isDeclaration = isListElementDeclaration(firstStatement, listVariable, indexName, parameterType); final String contentVariableName; @NonNls final String finalString; final PsiStatement statementToSkip; if (isDeclaration) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) firstStatement; assert declarationStatement != null; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; contentVariableName = variable.getName(); statementToSkip = declarationStatement; if (variable.hasModifierProperty(PsiModifier.FINAL)) { finalString = "final "; } else { finalString = ""; } } else { final String collectionName; if (listReference == null) { collectionName = null; } else { collectionName = listReference.getReferenceName(); } contentVariableName = createNewVariableName(forStatement, parameterType, collectionName); finalString = ""; statementToSkip = null; } @NonNls final StringBuilder out = new StringBuilder(); out.append("for("); out.append(finalString); out.append(typeString); out.append(' '); out.append(contentVariableName); out.append(": "); @NonNls final String listName; if (listReference == null) { listName = "this"; } else { listName = listReference.getText(); } out.append(listName); out.append(')'); if (body != null) { replaceCollectionGetAccess( body, contentVariableName, listVariable, indexName, statementToSkip, out); } return out.toString(); }
@Override protected void invokeImpl(final PsiClass targetClass) { if (CreateFromUsageUtils.isValidReference(myReferenceExpression, true)) { return; } final Project project = myReferenceExpression.getProject(); PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); final PsiFile targetFile = targetClass.getContainingFile(); PsiType[] expectedTypes = CreateFromUsageUtils.guessType(myReferenceExpression, false); PsiType type = expectedTypes[0]; String varName = myReferenceExpression.getReferenceName(); PsiExpression initializer = null; boolean isInline = false; PsiExpression[] expressions = CreateFromUsageUtils.collectExpressions( myReferenceExpression, PsiMember.class, PsiFile.class); PsiStatement anchor = getAnchor(expressions); if (anchor instanceof PsiExpressionStatement && ((PsiExpressionStatement) anchor).getExpression() instanceof PsiAssignmentExpression) { PsiAssignmentExpression assignment = (PsiAssignmentExpression) ((PsiExpressionStatement) anchor).getExpression(); if (assignment.getLExpression().textMatches(myReferenceExpression)) { initializer = assignment.getRExpression(); isInline = true; } } PsiDeclarationStatement decl = factory.createVariableDeclarationStatement(varName, type, initializer); TypeExpression expression = new TypeExpression(project, expectedTypes); if (isInline) { final PsiExpression expr = ((PsiExpressionStatement) anchor).getExpression(); final PsiElement semicolon = expr.getNextSibling(); if (semicolon != null) { final PsiElement nextSibling = semicolon.getNextSibling(); if (nextSibling != null) { decl.addRange(nextSibling, anchor.getLastChild()); } } decl = (PsiDeclarationStatement) anchor.replace(decl); } else { decl = (PsiDeclarationStatement) anchor.getParent().addBefore(decl, anchor); } PsiVariable var = (PsiVariable) decl.getDeclaredElements()[0]; boolean isFinal = CodeStyleSettingsManager.getSettings(project).GENERATE_FINAL_LOCALS && !CreateFromUsageUtils.isAccessedForWriting(expressions); PsiUtil.setModifierProperty(var, PsiModifier.FINAL, isFinal); var = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(var); if (var == null) return; TemplateBuilderImpl builder = new TemplateBuilderImpl(var); builder.replaceElement(var.getTypeElement(), expression); builder.setEndVariableAfter(var.getNameIdentifier()); Template template = builder.buildTemplate(); final Editor newEditor = positionCursor(project, targetFile, var); TextRange range = var.getTextRange(); newEditor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset()); startTemplate( newEditor, template, project, new TemplateEditingAdapter() { @Override public void templateFinished(Template template, boolean brokenOff) { PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument()); final int offset = newEditor.getCaretModel().getOffset(); final PsiLocalVariable localVariable = PsiTreeUtil.findElementOfClassAtOffset( targetFile, offset, PsiLocalVariable.class, false); if (localVariable != null) { ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { CodeStyleManager.getInstance(project).reformat(localVariable); } }); } } }); }
@Nullable private String createCollectionIterationText(@NotNull PsiForStatement forStatement) throws IncorrectOperationException { final PsiStatement body = forStatement.getBody(); final PsiStatement firstStatement = getFirstStatement(body); final PsiStatement initialization = forStatement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return null; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization; final PsiElement declaredIterator = declaration.getDeclaredElements()[0]; if (!(declaredIterator instanceof PsiVariable)) { return null; } final PsiVariable iteratorVariable = (PsiVariable) declaredIterator; final PsiMethodCallExpression initializer = (PsiMethodCallExpression) iteratorVariable.getInitializer(); if (initializer == null) { return null; } final PsiType iteratorType = initializer.getType(); if (iteratorType == null) { return null; } final PsiType iteratorContentType = extractContentTypeFromType(iteratorType); final PsiType iteratorVariableType = iteratorVariable.getType(); final PsiType contentType; final PsiClassType javaLangObject = TypeUtils.getObjectType(forStatement); if (iteratorContentType == null) { final PsiType iteratorVariableContentType = extractContentTypeFromType(iteratorVariableType); if (iteratorVariableContentType == null) { contentType = javaLangObject; } else { contentType = iteratorVariableContentType; } } else { contentType = iteratorContentType; } final PsiReferenceExpression methodExpression = initializer.getMethodExpression(); final PsiExpression collection = methodExpression.getQualifierExpression(); final String iteratorName = iteratorVariable.getName(); final boolean isDeclaration = isIteratorNextDeclaration(firstStatement, iteratorName, contentType); final PsiStatement statementToSkip; @NonNls final String finalString; final String contentVariableName; if (isDeclaration) { final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) firstStatement; assert declarationStatement != null; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiVariable)) { return null; } final PsiVariable variable = (PsiVariable) declaredElement; contentVariableName = variable.getName(); statementToSkip = declarationStatement; if (variable.hasModifierProperty(PsiModifier.FINAL)) { finalString = "final "; } else { finalString = ""; } } else { if (collection instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) collection; final String collectionName = referenceExpression.getReferenceName(); contentVariableName = createNewVariableName(forStatement, contentType, collectionName); } else { contentVariableName = createNewVariableName(forStatement, contentType, null); } final Project project = forStatement.getProject(); final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (codeStyleSettings.GENERATE_FINAL_LOCALS) { finalString = "final "; } else { finalString = ""; } statementToSkip = null; } final String contentTypeString = contentType.getCanonicalText(); @NonNls final StringBuilder out = new StringBuilder(); out.append("for("); out.append(finalString); out.append(contentTypeString); out.append(' '); out.append(contentVariableName); out.append(": "); if (!contentType.equals(javaLangObject)) { @NonNls final String iterableTypeString = "java.lang.Iterable<" + contentTypeString + '>'; if (iteratorContentType == null) { out.append('('); out.append(iterableTypeString); out.append(')'); } } if (collection == null) { out.append("this"); } else { out.append(collection.getText()); } out.append(')'); replaceIteratorNext( body, contentVariableName, iteratorName, statementToSkip, out, contentType); return out.toString(); }
@Nullable private static String getCollectionsAddAllText(PsiForStatement forStatement) throws IncorrectOperationException { final PsiExpression expression = forStatement.getCondition(); final PsiBinaryExpression condition = (PsiBinaryExpression) ParenthesesUtils.stripParentheses(expression); if (condition == null) { return null; } final PsiStatement initialization = forStatement.getInitialization(); if (initialization == null) { return null; } if (!(initialization instanceof PsiDeclarationStatement)) { return null; } final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); if (declaredElements.length != 1) { return null; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiLocalVariable)) { return null; } final PsiLocalVariable variable = (PsiLocalVariable) declaredElement; final String collectionText = buildCollectionText(forStatement); final PsiArrayAccessExpression arrayAccessExpression = getArrayAccessExpression(forStatement); if (arrayAccessExpression == null) { return null; } final PsiExpression arrayExpression = arrayAccessExpression.getArrayExpression(); final String arrayText = arrayExpression.getText(); final PsiExpression indexExpression = arrayAccessExpression.getIndexExpression(); final String fromOffsetText = buildFromOffsetText(indexExpression, variable); if (fromOffsetText == null) { return null; } final PsiExpression limit; final IElementType tokenType = condition.getOperationTokenType(); if (tokenType == JavaTokenType.LT || tokenType == JavaTokenType.LE) { limit = condition.getROperand(); } else { limit = condition.getLOperand(); } @NonNls final String toOffsetText = buildToOffsetText(limit, tokenType == JavaTokenType.LE || tokenType == JavaTokenType.GE); if (toOffsetText == null) { return null; } if (fromOffsetText.equals("0") && toOffsetText.equals(arrayText + ".length") && PsiUtil.isLanguageLevel5OrHigher(forStatement)) { return "java.util.Collections.addAll(" + collectionText + ',' + arrayText + ");"; } else { @NonNls final StringBuilder buffer = new StringBuilder(); buffer.append(collectionText); buffer.append('.'); buffer.append("addAll(java.util.Arrays.asList("); buffer.append(arrayText); buffer.append(')'); if (!fromOffsetText.equals("0") || !toOffsetText.equals(arrayText + ".length")) { buffer.append(".subList("); buffer.append(fromOffsetText); buffer.append(", "); buffer.append(toOffsetText); buffer.append(')'); } buffer.append(");"); return buffer.toString(); } }
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); }
public void run() { try { final boolean rebindNeeded2 = !myVariableName.equals(myFieldName) || myRebindNeeded; final PsiReference[] refs; if (rebindNeeded2) { refs = ReferencesSearch.search(myLocal, GlobalSearchScope.projectScope(myProject), false) .toArray(new PsiReference[0]); } else { refs = null; } final PsiMethod enclosingConstructor = BaseExpressionToFieldHandler.getEnclosingConstructor(myDestinationClass, myLocal); myField = mySettings.isIntroduceEnumConstant() ? EnumConstantsUtil.createEnumConstant(myDestinationClass, myLocal, myFieldName) : createField( myLocal, mySettings.getForcedType(), myFieldName, myInitializerPlace == IN_FIELD_DECLARATION); myField = (PsiField) myDestinationClass.add(myField); BaseExpressionToFieldHandler.setModifiers(myField, mySettings); if (!mySettings.isIntroduceEnumConstant()) { VisibilityUtil.fixVisibility(myOccurences, myField, mySettings.getFieldVisibility()); } myLocal.normalizeDeclaration(); PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) myLocal.getParent(); final BaseExpressionToFieldHandler.InitializationPlace finalInitializerPlace; if (myLocal.getInitializer() == null) { finalInitializerPlace = IN_FIELD_DECLARATION; } else { finalInitializerPlace = myInitializerPlace; } final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory(); switch (finalInitializerPlace) { case IN_FIELD_DECLARATION: declarationStatement.delete(); break; case IN_CURRENT_METHOD: PsiStatement statement = createAssignment(myLocal, myFieldName, factory); myAssignmentStatement = (PsiStatement) declarationStatement.replace(statement); break; case IN_CONSTRUCTOR: myAssignmentStatement = addInitializationToConstructors(myLocal, myField, enclosingConstructor, factory); break; case IN_SETUP_METHOD: myAssignmentStatement = addInitializationToSetUp(myLocal, myField, factory); } if (enclosingConstructor != null && myInitializerPlace == IN_CONSTRUCTOR) { PsiStatement statement = createAssignment(myLocal, myFieldName, factory); myAssignmentStatement = (PsiStatement) declarationStatement.replace(statement); } if (rebindNeeded2) { for (final PsiReference reference : refs) { if (reference != null) { // expr = RefactoringUtil.outermostParenthesizedExpression(expr); RefactoringUtil.replaceOccurenceWithFieldRef( (PsiExpression) reference, myField, myDestinationClass); // replaceOccurenceWithFieldRef((PsiExpression)reference, field, aaClass); } } // RefactoringUtil.renameVariableReferences(local, pPrefix + fieldName, // GlobalSearchScope.projectScope(myProject)); } } catch (IncorrectOperationException e) { LOG.error(e); } }