blob: 91fc85c016c0634ccc71d5b8673168330f721592 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.refactoring.rename;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class JavaNameSuggestionProvider implements NameSuggestionProvider {
@Nullable
public SuggestedNameInfo getSuggestedNames(final PsiElement element, final PsiElement nameSuggestionContext, Set<String> result) {
if (!element.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return null;
String initialName = UsageViewUtil.getShortName(element);
SuggestedNameInfo info = suggestNamesForElement(element, nameSuggestionContext);
if (info != null) {
info = JavaCodeStyleManager.getInstance(element.getProject()).suggestUniqueVariableName(info, element, true, true);
}
String parameterName = null;
String superMethodName = null;
if (nameSuggestionContext instanceof PsiParameter) {
final PsiElement nameSuggestionContextParent = nameSuggestionContext.getParent();
if (nameSuggestionContextParent instanceof PsiParameterList) {
final PsiElement parentOfParent = nameSuggestionContextParent.getParent();
if (parentOfParent instanceof PsiMethod) {
final String propName = PropertyUtil.getPropertyName((PsiMethod)parentOfParent);
if (propName != null) {
parameterName = propName;
}
superMethodName = getSuperMethodName((PsiParameter) nameSuggestionContext, (PsiMethod) parentOfParent);
}
}
}
final String[] strings = info != null ? info.names : ArrayUtil.EMPTY_STRING_ARRAY;
final ArrayList<String> list = new ArrayList<String>(Arrays.asList(strings));
final String[] properlyCased = suggestProperlyCasedName(element);
if (properlyCased != null) {
Collections.addAll(list, properlyCased);
}
if (parameterName != null && !list.contains(parameterName)) {
list.add(parameterName);
}
if (superMethodName != null && !list.contains(superMethodName)) {
list.add(0, superMethodName);
}
if (!list.contains(initialName)) {
list.add(initialName);
}
else {
int i = list.indexOf(initialName);
list.remove(i);
list.add(initialName);
}
ContainerUtil.removeDuplicates(list);
result.addAll(list);
return info;
}
@Nullable
private static String getSuperMethodName(final PsiParameter psiParameter, final PsiMethod method) {
final int index = method.getParameterList().getParameterIndex(psiParameter);
final PsiMethod[] superMethods = method.findSuperMethods();
for (PsiMethod superMethod : superMethods) {
final PsiParameterList superParameters = superMethod.getParameterList();
if (index < superParameters.getParametersCount()) {
return superParameters.getParameters() [index].getName();
}
}
return null;
}
@Nullable
private static String[] suggestProperlyCasedName(PsiElement psiElement) {
if (!(psiElement instanceof PsiNamedElement)) return null;
if (psiElement instanceof PsiFile) return null;
String name = ((PsiNamedElement)psiElement).getName();
if (name == null) return null;
String prefix = "";
if (psiElement instanceof PsiVariable) {
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(psiElement.getProject());
final VariableKind kind = codeStyleManager.getVariableKind((PsiVariable)psiElement);
prefix = codeStyleManager.getPrefixByVariableKind(kind);
if (kind == VariableKind.STATIC_FINAL_FIELD) {
final String[] words = NameUtil.splitNameIntoWords(name);
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < words.length; i++) {
String word = words[i];
if (i > 0) buffer.append('_');
buffer.append(StringUtil.toUpperCase(word));
}
return new String[] {buffer.toString()};
}
}
final List<String> result = new ArrayList<String>();
result.add(suggestProperlyCasedName(prefix, NameUtil.splitNameIntoWords(name)));
if (name.startsWith(prefix)) {
name = name.substring(prefix.length());
result.add(suggestProperlyCasedName(prefix, NameUtil.splitNameIntoWords(name)));
}
result.add(suggestProperlyCasedName(prefix, NameUtil.splitNameIntoWords(name.toLowerCase())));
return ArrayUtil.toStringArray(result);
}
private static String suggestProperlyCasedName(String prefix, String[] words) {
StringBuilder buffer = new StringBuilder(prefix);
for (int i = 0; i < words.length; i++) {
String word = words[i];
final boolean prefixRequiresCapitalization = prefix.length() > 0 && !StringUtil.endsWithChar(prefix, '_');
if (i > 0 || prefixRequiresCapitalization) {
buffer.append(StringUtil.capitalize(word));
}
else {
buffer.append(StringUtil.decapitalize(word));
}
}
return buffer.toString();
}
@Nullable
private static SuggestedNameInfo suggestNamesForElement(final PsiElement element, PsiElement nameSuggestionContext) {
PsiVariable var = null;
if (element instanceof PsiVariable) {
var = (PsiVariable)element;
}
else if (element instanceof PsiIdentifier) {
PsiIdentifier identifier = (PsiIdentifier)element;
if (identifier.getParent() instanceof PsiVariable) {
var = (PsiVariable)identifier.getParent();
}
}
if (var == null) return null;
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(element.getProject());
VariableKind variableKind = codeStyleManager.getVariableKind(var);
final SuggestedNameInfo nameInfo = codeStyleManager.suggestVariableName(variableKind, null, var.getInitializer(), var.getType());
final PsiExpression expression = PsiTreeUtil.getParentOfType(nameSuggestionContext, PsiExpression.class, false);
if (expression != null) {
return new SuggestedNameInfo.Delegate(codeStyleManager.suggestVariableName(variableKind, null, expression, var.getType()).names, nameInfo);
}
return nameInfo;
}
}