diff --git a/source/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/source/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index fdefb5c274a4..aff03889e6e2 100644 --- a/source/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/source/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -1,14 +1,13 @@ package com.intellij.codeInsight.daemon.impl; +import com.intellij.codeInsight.CodeInsightColors; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.CodeInsightUtil; -import com.intellij.codeInsight.CodeInsightColors; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil; import com.intellij.codeInsight.daemon.impl.quickfix.*; -import com.intellij.codeInsight.intention.impl.CreateFieldFromParameterAction; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -275,8 +274,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { count = myRefCountHolder.getReadRefCount(field); if (count == 0) { - String message = MessageFormat.format(PRIVATE_FIELD_IS_NOT_USED_FOR_READING, - new Object[]{identifier.getText()}); + String message = MessageFormat.format(PRIVATE_FIELD_IS_NOT_USED_FOR_READING, new Object[]{identifier.getText()}); final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message); QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(field)); QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterAction(true, field)); @@ -338,9 +336,6 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { PsiIdentifier identifier = parameter.getNameIdentifier(); String message = MessageFormat.format(PARAMETER_IS_NOT_USED, new Object[]{identifier.getText()}); final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message); - if (method.isConstructor()) { - QuickFixAction.registerQuickFixAction(highlightInfo, new CreateFieldFromParameterAction(parameter)); - } QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedParameterFix(parameter)); return highlightInfo; } diff --git a/source/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterAction.java b/source/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterAction.java index 2bcfec98e8d8..0ba48df9ec1b 100644 --- a/source/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterAction.java +++ b/source/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterAction.java @@ -11,6 +11,8 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.PsiSearchHelper; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; @@ -22,47 +24,97 @@ import java.util.List; public class CreateFieldFromParameterAction implements IntentionAction { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.CreateFieldFromParameterAction"); - private final PsiParameter myParameter; - private PsiType myType; + private PsiParameter myParameter; + private final boolean forcedParameter; + public CreateFieldFromParameterAction() { + myParameter = null; + forcedParameter = false; + } public CreateFieldFromParameterAction(PsiParameter parameter) { myParameter = parameter; - myType = myParameter.getType(); - if (myType instanceof PsiEllipsisType) myType = ((PsiEllipsisType)myType).toArrayType(); + forcedParameter = true; + } + + private PsiType getType() { + if (myParameter == null) return null; + PsiType type = myParameter.getType(); + if (type instanceof PsiEllipsisType) type = ((PsiEllipsisType)type).toArrayType(); + return type; } public String getText() { - final String text = MessageFormat.format("Create Field For Parameter ''{0}''", new Object[]{myParameter.getName(), }); - return text; + return MessageFormat.format("Create Field For Parameter ''{0}''", new Object[]{myParameter.getName(), }); } public boolean isAvailable(Project project, Editor editor, PsiFile file) { + myParameter = forcedParameter ? myParameter : findParameterAtCursor(file, editor); + final PsiType type = getType(); return myParameter != null && myParameter.isValid() && myParameter.getDeclarationScope() instanceof PsiMethod && myParameter.getManager().isInProject(myParameter) - && myType.isValid() + && type != null + && type.isValid() + && !isParameterAssignedToField(myParameter) ; } + private static boolean isParameterAssignedToField(final PsiParameter parameter) { + final PsiSearchHelper searchHelper = parameter.getManager().getSearchHelper(); + final PsiReference[] references = searchHelper.findReferences(parameter, new LocalSearchScope(parameter.getDeclarationScope()), false); + for (int i = 0; i < references.length; i++) { + PsiReference reference = references[i]; + if (!(reference instanceof PsiReferenceExpression)) continue; + final PsiReferenceExpression expression = (PsiReferenceExpression)reference; + if (!(expression.getParent() instanceof PsiAssignmentExpression)) continue; + final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)expression.getParent(); + if (assignmentExpression.getRExpression() != expression) continue; + final PsiExpression lExpression = assignmentExpression.getLExpression(); + if (!(lExpression instanceof PsiReferenceExpression)) continue; + final PsiElement element = ((PsiReferenceExpression)lExpression).resolve(); + if (!(element instanceof PsiField)) continue; + return true; + } + return false; + } + + private static PsiParameter findParameterAtCursor(final PsiFile file, final Editor editor) { + final int offset = editor.getCaretModel().getOffset(); + PsiElement element = file.findElementAt(offset); + if (element == null) return null; + PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class); + if (parameter != null) { + return parameter; + } + if (!(element instanceof PsiWhiteSpace)) { + element = file.findElementAt(offset-1); + if (element == null) return null; + parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class); + } + + return parameter; + } + public String getFamilyName() { return "Create Field for Parameter"; } public void invoke(Project project, Editor editor, PsiFile file) { - invoke(project, !ApplicationManager.getApplication().isUnitTestMode()); + invoke(project, editor, file, !ApplicationManager.getApplication().isUnitTestMode()); } - private void invoke(final Project project, boolean isInteractive) { + private void invoke(final Project project, Editor editor, PsiFile file, boolean isInteractive) { + myParameter = forcedParameter ? myParameter : findParameterAtCursor(file, editor); if (!CodeInsightUtil.prepareFileForWrite(myParameter.getContainingFile())) return; IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace(); - + final PsiType type = getType(); final CodeStyleManager styleManager = CodeStyleManager.getInstance(project); final String parameterName = myParameter.getName(); String propertyName = styleManager.variableNameToPropertyName(parameterName, VariableKind.PARAMETER); - SuggestedNameInfo suggestedNameInfo = styleManager.suggestVariableName(VariableKind.FIELD, propertyName, null, myType); + SuggestedNameInfo suggestedNameInfo = styleManager.suggestVariableName(VariableKind.FIELD, propertyName, null, type); String[] names = suggestedNameInfo.names; String fieldNameToCalc; @@ -74,7 +126,9 @@ public class CreateFieldFromParameterAction implements IntentionAction { List namesList = new ArrayList(); namesList.addAll(Arrays.asList(names)); String defaultName = styleManager.propertyNameToVariableName(propertyName, VariableKind.FIELD); - if (!namesList.contains(defaultName)) namesList.add(0, defaultName); + if (!namesList.contains(defaultName)) { + namesList.add(0, defaultName); + } else { Collections.swap(namesList, 0, namesList.indexOf(defaultName)); } @@ -83,7 +137,7 @@ public class CreateFieldFromParameterAction implements IntentionAction { CreateFieldFromParameterDialog dialog = new CreateFieldFromParameterDialog( project, names, - myType.getCanonicalText(), targetClass); + type.getCanonicalText(), targetClass); dialog.show(); if (!dialog.isOK()) return; @@ -106,7 +160,7 @@ public class CreateFieldFromParameterAction implements IntentionAction { PsiManager psiManager = PsiManager.getInstance(project); PsiElementFactory factory = psiManager.getElementFactory(); - PsiField field = factory.createField(fieldName, myType); + PsiField field = factory.createField(fieldName, type); if (isFinal) { PsiModifierList modifierList = field.getModifierList(); diff --git a/source/com/intellij/codeInsight/intention/impl/config/IntentionManagerImpl.java b/source/com/intellij/codeInsight/intention/impl/config/IntentionManagerImpl.java index 5dad8b0502b1..3927627b55a7 100644 --- a/source/com/intellij/codeInsight/intention/impl/config/IntentionManagerImpl.java +++ b/source/com/intellij/codeInsight/intention/impl/config/IntentionManagerImpl.java @@ -41,6 +41,7 @@ public class IntentionManagerImpl extends IntentionManager { registerIntentionAndMetaData(new EJBImplementationAction(), new String[]{"EJB"}); registerIntentionAndMetaData(new EJBDeclarationAction(), new String[]{"EJB"}); + addAction(new CreateFieldFromParameterAction()); } public void registerIntentionAndMetaData(IntentionAction action, String[] category) {