update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / refactoring / extractMethod / InputVariables.java
blob655eba6ec29e0945dfa014d68393f239503687d6
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * User: anna
19 * Date: 22-Jun-2009
21 package com.intellij.refactoring.extractMethod;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.util.Pair;
25 import com.intellij.psi.*;
26 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
27 import com.intellij.psi.codeStyle.VariableKind;
28 import com.intellij.psi.controlFlow.ControlFlow;
29 import com.intellij.psi.search.LocalSearchScope;
30 import com.intellij.psi.search.searches.ReferencesSearch;
31 import com.intellij.psi.util.PsiTreeUtil;
32 import com.intellij.refactoring.util.ParameterTablePanel;
33 import com.intellij.refactoring.util.duplicates.DuplicatesFinder;
34 import com.intellij.util.ArrayUtil;
36 import java.util.*;
38 public class InputVariables {
39 private final List<ParameterTablePanel.VariableData> myInputVariables;
41 private List<? extends PsiVariable> myInitialParameters;
42 private final Project myProject;
43 private final LocalSearchScope myScope;
45 private ParametersFolder myFolding;
46 private boolean myFoldingAvailable;
48 public InputVariables(final List<? extends PsiVariable> inputVariables,
49 Project project,
50 LocalSearchScope scope,
51 boolean foldingAvailable) {
52 myInitialParameters = inputVariables;
53 myProject = project;
54 myScope = scope;
55 myFoldingAvailable = foldingAvailable;
56 myFolding = new ParametersFolder();
57 myInputVariables = wrapInputVariables(inputVariables);
60 /**
61 * copy use only
63 public InputVariables(List<ParameterTablePanel.VariableData> inputVariables,
64 Project project,
65 LocalSearchScope scope) {
66 myProject = project;
67 myScope = scope;
68 myInputVariables = new ArrayList<ParameterTablePanel.VariableData>(inputVariables);
71 public boolean isFoldable() {
72 return myFolding.isFoldable();
75 public ArrayList<ParameterTablePanel.VariableData> wrapInputVariables(final List<? extends PsiVariable> inputVariables) {
76 final ArrayList<ParameterTablePanel.VariableData> inputData = new ArrayList<ParameterTablePanel.VariableData>(inputVariables.size());
77 for (PsiVariable var : inputVariables) {
78 String name = var.getName();
79 if (!(var instanceof PsiParameter)) {
80 JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(myProject);
81 VariableKind kind = codeStyleManager.getVariableKind(var);
82 name = codeStyleManager.variableNameToPropertyName(name, kind);
83 name = codeStyleManager.propertyNameToVariableName(name, VariableKind.PARAMETER);
85 PsiType type = var.getType();
86 if (type instanceof PsiEllipsisType) {
87 type = ((PsiEllipsisType)type).toArrayType();
90 ParameterTablePanel.VariableData data = new ParameterTablePanel.VariableData(var, type);
91 data.name = name;
92 data.passAsParameter = true;
93 inputData.add(data);
95 if (myFoldingAvailable) myFolding.isParameterFoldable(data, myScope, inputVariables);
99 if (myFoldingAvailable) {
100 final Set<ParameterTablePanel.VariableData> toDelete = new HashSet<ParameterTablePanel.VariableData>();
101 for (int i = inputData.size() - 1; i >=0; i--) {
102 final ParameterTablePanel.VariableData data = inputData.get(i);
103 if (myFolding.isParameterSafeToDelete(data, myScope)) {
104 toDelete.add(data);
107 inputData.removeAll(toDelete);
111 return inputData;
114 public List<ParameterTablePanel.VariableData> getInputVariables() {
115 return myInputVariables;
118 public PsiExpression replaceWrappedReferences(PsiElement[] elements, PsiExpression expression) {
119 if (!myFoldingAvailable) return expression;
121 boolean update = elements[0] == expression;
122 for (ParameterTablePanel.VariableData inputVariable : myInputVariables) {
123 myFolding.foldParameterUsagesInBody(inputVariable, elements, myScope);
125 return update ? (PsiExpression)elements[0] : expression;
128 public boolean toDeclareInsideBody(PsiVariable variable) {
129 final ArrayList<ParameterTablePanel.VariableData> knownVars = new ArrayList<ParameterTablePanel.VariableData>(myInputVariables);
130 for (ParameterTablePanel.VariableData data : knownVars) {
131 if (data.variable.equals(variable)) {
132 return false;
135 return !myFolding.wasExcluded(variable);
138 public boolean contains(PsiVariable variable) {
139 for (ParameterTablePanel.VariableData data : myInputVariables) {
140 if (data.variable.equals(variable)) return true;
142 return false;
145 public void removeParametersUsedInExitsOnly(PsiElement codeFragment,
146 Collection<PsiStatement> exitStatements,
147 ControlFlow controlFlow,
148 int startOffset,
149 int endOffset) {
150 final LocalSearchScope scope = new LocalSearchScope(codeFragment);
151 Variables:
152 for (Iterator<ParameterTablePanel.VariableData> iterator = myInputVariables.iterator(); iterator.hasNext();) {
153 final ParameterTablePanel.VariableData data = iterator.next();
154 for (PsiReference ref : ReferencesSearch.search(data.variable, scope)) {
155 PsiElement element = ref.getElement();
156 int elementOffset = controlFlow.getStartOffset(element);
157 if (elementOffset >= startOffset && elementOffset <= endOffset) {
158 if (!isInExitStatements(element, exitStatements)) continue Variables;
161 iterator.remove();
165 private static boolean isInExitStatements(PsiElement element, Collection<PsiStatement> exitStatements) {
166 for (PsiStatement exitStatement : exitStatements) {
167 if (PsiTreeUtil.isAncestor(exitStatement, element, false)) return true;
169 return false;
173 public InputVariables copy() {
174 final InputVariables inputVariables = new InputVariables(myInputVariables, myProject, myScope);
175 inputVariables.myFoldingAvailable = myFoldingAvailable;
176 inputVariables.myFolding = myFolding;
177 inputVariables.myInitialParameters = myInitialParameters;
178 return inputVariables;
182 public void appendCallArguments(ParameterTablePanel.VariableData data, StringBuilder buffer) {
183 if (myFoldingAvailable) {
184 buffer.append(myFolding.getGeneratedCallArgument(data));
185 } else {
186 buffer.append(data.variable.getName());
190 public void setFoldingAvailable(boolean foldingAvailable) {
191 myFoldingAvailable = foldingAvailable;
193 myFolding.clear();
194 myInputVariables.clear();
195 myInputVariables.addAll(wrapInputVariables(myInitialParameters));
198 public void annotateWithParameter(PsiJavaCodeReferenceElement reference) {
199 for (ParameterTablePanel.VariableData data : myInputVariables) {
200 final PsiElement element = reference.resolve();
201 if (data.variable.equals(element)) {
202 PsiType type = data.variable.getType();
203 final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(reference, PsiMethodCallExpression.class);
204 if (methodCallExpression != null) {
205 int idx = ArrayUtil.find(methodCallExpression.getArgumentList().getExpressions(), reference);
206 if (idx > -1) {
207 final PsiMethod psiMethod = methodCallExpression.resolveMethod();
208 if (psiMethod != null) {
209 final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
210 if (idx >= parameters.length) { //vararg parameter
211 idx = parameters.length - 1;
212 if (idx >= 0) { //incomplete code
213 type = parameters[idx].getType();
216 if (type instanceof PsiEllipsisType) {
217 type = ((PsiEllipsisType)type).getComponentType();
222 if (!myFoldingAvailable || !myFolding.annotateWithParameter(data, reference)) {
223 reference.putUserData(DuplicatesFinder.PARAMETER, Pair.create(data.variable, type));
229 public boolean isFoldingSelectedByDefault() {
230 return myFolding.isFoldingSelectedByDefault();