Merge branch 'master' into upsource-master

This commit is contained in:
Evgeny Pasynkov
2012-06-18 14:06:37 +02:00
304 changed files with 6360 additions and 2318 deletions
@@ -62,7 +62,9 @@ public class JavaCompletionSorting {
if (!smart) {
ContainerUtil.addIfNotNull(afterNegativeStats, preferStatics(position, expectedTypes));
}
afterNegativeStats.add(new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type, position));
if (!JavaCompletionData.START_FOR.accepts(position)) {
afterNegativeStats.add(new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type, position));
}
ContainerUtil.addIfNotNull(afterNegativeStats, recursion(parameters, expectedTypes));
if (!smart && !afterNew) {
afterNegativeStats.add(new PreferExpected(false, expectedTypes));
@@ -37,7 +37,8 @@ public class JavaColorProvider implements ElementColorProvider {
if (type != null) {
final PsiClass aClass = PsiTypesUtil.getPsiClass(type);
if (aClass != null) {
if ("java.awt.Color".equals(aClass.getQualifiedName())) {
final String fqn = aClass.getQualifiedName();
if ("java.awt.Color".equals(fqn) || "javax.swing.plaf.ColorUIResource".equals(fqn)) {
return getColor(expr.getArgumentList());
}
}
@@ -106,8 +107,7 @@ public class JavaColorProvider implements ElementColorProvider {
PsiExpression[] expr = argumentList.getExpressions();
ColorConstructors type = getConstructorType(argumentList.getExpressionTypes());
PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject());
assert type != null;
switch (type) {
@@ -1278,6 +1278,7 @@ public class HighlightMethodUtil {
if (classReference != null) {
ConstructorParametersFixer.registerFixActions(classReference, constructorCall, info, getFixRange(infoElement));
ChangeMethodSignatureFromUsageFix.registerIntentions(results, list, info, null);
ChangeTypeArgumentsFix.registerIntentions(results, list, info, aClass);
ConvertDoubleToFloatFix.registerIntentions(results, list, info, null);
PermuteArgumentsFix.registerFix(info, constructorCall, toMethodCandidates(results), getFixRange(list));
ChangeParameterClassFix.registerQuickFixActions(constructorCall, list, info);
@@ -122,6 +122,7 @@ public class ChangeParameterClassFix extends ExtendsListFix {
if (rClass instanceof PsiAnonymousClass) return;
if (rClass.isInheritor(lClass, true)) return;
if (lClass.isInheritor(rClass, true)) return;
if (lClass == rClass) return;
QuickFixAction.registerQuickFixAction(info, new ChangeParameterClassFix(rClass, (PsiClassType)lType));
}
@@ -0,0 +1,165 @@
/*
* Copyright 2000-2012 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.
*/
/**
* Created by IntelliJ IDEA.
* User: cdr
* Date: Nov 13, 2002
* Time: 3:26:50 PM
* To change this template use Options | File Templates.
*/
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
public class ChangeTypeArgumentsFix implements IntentionAction, HighPriorityAction {
private final PsiMethod myTargetMethod;
private final PsiClass myPsiClass;
private final PsiExpression[] myExpressions;
private static final Logger LOG = Logger.getInstance("#" + ChangeTypeArgumentsFix.class.getName());
private final PsiNewExpression myNewExpression;
ChangeTypeArgumentsFix(@NotNull PsiMethod targetMethod,
PsiClass psiClass,
@NotNull PsiExpression[] expressions,
@NotNull PsiElement context) {
myTargetMethod = targetMethod;
myPsiClass = psiClass;
myExpressions = expressions;
myNewExpression = PsiTreeUtil.getParentOfType(context, PsiNewExpression.class);
}
@Override
@NotNull
public String getText() {
final PsiSubstitutor substitutor = inferTypeArguments();
return "Change type arguments to <" + StringUtil.join(myPsiClass.getTypeParameters(), new Function<PsiTypeParameter, String>() {
@Override
public String fun(PsiTypeParameter typeParameter) {
return substitutor.substitute(typeParameter).getPresentableText();
}
}, ", ") + ">";
}
@Override
@NotNull
public String getFamilyName() {
return "Change type arguments";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
final PsiTypeParameter[] typeParameters = myPsiClass.getTypeParameters();
if (typeParameters.length > 0) {
if (myNewExpression != null && myNewExpression.isValid() && myNewExpression.getArgumentList() != null) {
final PsiJavaCodeReferenceElement reference = myNewExpression.getClassOrAnonymousClassReference();
if (reference != null) {
final PsiReferenceParameterList parameterList = reference.getParameterList();
if (parameterList != null) {
final PsiSubstitutor substitutor = inferTypeArguments();
final PsiParameter[] parameters = myTargetMethod.getParameterList().getParameters();
if (parameters.length != myExpressions.length) return false;
for (int i = 0, length = parameters.length; i < length; i++) {
PsiParameter parameter = parameters[i];
final PsiType expectedType = substitutor.substitute(parameter.getType());
if (!myExpressions[i].isValid()) return false;
final PsiType actualType = myExpressions[i].getType();
if (expectedType == null || actualType == null || !TypeConversionUtil.isAssignable(expectedType, actualType)) return false;
}
return true;
}
}
}
}
return false;
}
@Override
public void invoke(@NotNull final Project project, Editor editor, final PsiFile file) {
if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
final PsiTypeParameter[] typeParameters = myPsiClass.getTypeParameters();
final PsiSubstitutor psiSubstitutor = inferTypeArguments();
final PsiJavaCodeReferenceElement reference = myNewExpression.getClassOrAnonymousClassReference();
LOG.assertTrue(reference != null, myNewExpression);
final PsiReferenceParameterList parameterList = reference.getParameterList();
LOG.assertTrue(parameterList != null, myNewExpression);
PsiTypeElement[] elements = parameterList.getTypeParameterElements();
for (int i = elements.length - 1; i >= 0; i--) {
PsiTypeElement typeElement = elements[i];
final PsiType typeArg = psiSubstitutor.substitute(typeParameters[i]);
typeElement.replace(JavaPsiFacade.getElementFactory(project).createTypeElement(typeArg));
}
}
private PsiSubstitutor inferTypeArguments() {
final JavaPsiFacade facade = JavaPsiFacade.getInstance(myNewExpression.getProject());
final PsiResolveHelper resolveHelper = facade.getResolveHelper();
final PsiParameter[] parameters = myTargetMethod.getParameterList().getParameters();
final PsiExpressionList argumentList = myNewExpression.getArgumentList();
LOG.assertTrue(argumentList != null);
final PsiExpression[] expressions = argumentList.getExpressions();
return resolveHelper.inferTypeArguments(myPsiClass.getTypeParameters(), parameters, expressions,
PsiSubstitutor.EMPTY,
myNewExpression.getParent(),
DefaultParameterTypeInferencePolicy.INSTANCE);
}
public static void registerIntentions(@NotNull JavaResolveResult[] candidates,
@NotNull PsiExpressionList list,
@NotNull HighlightInfo highlightInfo,
PsiClass psiClass) {
if (candidates.length == 0) return;
PsiExpression[] expressions = list.getExpressions();
for (JavaResolveResult candidate : candidates) {
registerIntention(expressions, highlightInfo, psiClass, candidate, list);
}
}
private static void registerIntention(@NotNull PsiExpression[] expressions,
@NotNull HighlightInfo highlightInfo,
PsiClass psiClass,
@NotNull JavaResolveResult candidate,
@NotNull PsiElement context) {
if (!candidate.isStaticsScopeCorrect()) return;
PsiMethod method = (PsiMethod)candidate.getElement();
PsiSubstitutor substitutor = candidate.getSubstitutor();
if (method != null && context.getManager().isInProject(method)) {
final ChangeTypeArgumentsFix fix = new ChangeTypeArgumentsFix(method, psiClass, expressions, context);
QuickFixAction.registerQuickFixAction(highlightInfo, null, fix);
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -59,14 +59,17 @@ public class InitializeFinalFieldInConstructorFix implements IntentionAction {
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
PsiClass containingClass = myField == null ? null : myField.getContainingClass();
return myField != null
&& myField.getManager().isInProject(myField)
&& !myField.hasModifierProperty(PsiModifier.STATIC)
&& myField.isValid()
&& !myField.hasInitializer()
&& containingClass != null
&& containingClass.getName() != null;
if (myField == null || myField.hasModifierProperty(PsiModifier.STATIC) || !myField.isValid() || myField.hasInitializer()) {
return false;
}
final PsiClass containingClass = myField.getContainingClass();
if (containingClass == null || containingClass.getName() == null){
return false;
}
final PsiManager manager = myField.getManager();
return manager != null && manager.isInProject(myField);
}
@Override
@@ -74,7 +77,9 @@ public class InitializeFinalFieldInConstructorFix implements IntentionAction {
if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
final PsiClass myClass = myField.getContainingClass();
if (myClass == null) {
return;
}
if (myClass.getConstructors().length == 0) {
createDefaultConstructor(myClass, project, editor, file);
}
@@ -158,7 +158,7 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
@Override
public void run() {
final LocateLibraryDialog dialog = new LocateLibraryDialog(currentModule, PathManager.getLibPath(), "annotations.jar",
QuickFixBundle.message("add.library.annotations.description"));
QuickFixBundle.message("add.library.annotations.description"));
dialog.show();
if (dialog.isOK()) {
new WriteCommandAction(project) {
@@ -212,12 +212,9 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
final Runnable doit = new Runnable() {
@Override
public void run() {
ModifiableRootModel model = ModuleRootManager.getInstance(currentModule).getModifiableModel();
final ModuleOrderEntry entry = model.addModuleOrderEntry(classModule);
if (ModuleRootManager.getInstance(currentModule).getFileIndex().isInTestSourceContent(classVFile)) {
entry.setScope(DependencyScope.TEST);
}
model.commit();
final boolean test = ModuleRootManager.getInstance(currentModule).getFileIndex().isInTestSourceContent(classVFile);
ModuleRootModificationUtil.addDependency(currentModule, classModule,
test ? DependencyScope.TEST : DependencyScope.COMPILE, false);
if (editor != null) {
final List<PsiClass> targetClasses = new ArrayList<PsiClass>();
for (PsiClass psiClass : classes) {
@@ -257,7 +254,8 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
if (entryForFile instanceof ExportableOrderEntry &&
((ExportableOrderEntry)entryForFile).getScope() == DependencyScope.TEST &&
!ModuleRootManager.getInstance(currentModule).getFileIndex().isInTestSourceContent(classVFile)) {
} else {
}
else {
continue;
}
}
@@ -361,9 +359,9 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
final Module classModule,
final Runnable doit) {
final String message = QuickFixBundle.message("orderEntry.fix.circular.dependency.warning", classModule.getName(),
circularModules.getFirst().getName(), circularModules.getSecond().getName());
circularModules.getFirst().getName(), circularModules.getSecond().getName());
if (ApplicationManager.getApplication().isUnitTestMode()) throw new RuntimeException(message);
ApplicationManager.getApplication().invokeLater(new Runnable(){
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (!project.isOpen()) return;
@@ -24,8 +24,7 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
@@ -34,15 +33,17 @@ import org.jetbrains.annotations.NotNull;
/**
* @author mike
* Date: Aug 20, 2002
* Date: Aug 20, 2002
*/
public class SetupJDKFix implements IntentionAction, HighPriorityAction {
private static final SetupJDKFix ourInstance = new SetupJDKFix();
public static SetupJDKFix getInstance() {
return ourInstance;
}
private SetupJDKFix() { }
private SetupJDKFix() {
}
@Override
@NotNull
@@ -70,9 +71,7 @@ public class SetupJDKFix implements IntentionAction, HighPriorityAction {
public void run() {
Module module = ModuleUtil.findModuleForPsiElement(file);
if (module != null) {
ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(module).getModifiableModel();
modifiableModel.inheritSdk();
modifiableModel.commit();
ModuleRootModificationUtil.setSdkInherited(module);
}
}
});
@@ -25,6 +25,7 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -32,8 +33,11 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.impl.light.LightMethodBuilder;
import com.intellij.psi.impl.light.LightTypeElement;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.util.RefactoringUtil;
@@ -100,7 +104,7 @@ public class GenerateMembersUtil {
element = element.getNextSibling();
}
if (element instanceof PsiField) {
PsiField field = (PsiField) element;
PsiField field = (PsiField)element;
PsiTypeElement typeElement = field.getTypeElement();
if (typeElement != null && !field.equals(typeElement.getParent())) {
field.normalizeDeclaration();
@@ -129,7 +133,7 @@ public class GenerateMembersUtil {
LOG.assertTrue(firstMember.isValid());
if (toEditMethodBody) {
PsiMethod method = (PsiMethod) firstMember;
PsiMethod method = (PsiMethod)firstMember;
PsiCodeBlock body = method.getBody();
if (body != null) {
PsiElement l = body.getFirstBodyElement();
@@ -154,7 +158,7 @@ public class GenerateMembersUtil {
int offset;
if (firstMember instanceof PsiMethod) {
PsiMethod method = (PsiMethod) firstMember;
PsiMethod method = (PsiMethod)firstMember;
PsiCodeBlock body = method.getBody();
if (body == null) {
offset = method.getTextRange().getStartOffset();
@@ -226,116 +230,226 @@ public class GenerateMembersUtil {
return substituteGenericMethod(method, substitutor, null);
}
public static PsiMethod substituteGenericMethod(PsiMethod method,
final PsiSubstitutor substitutor,
@Nullable final PsiElement target) {
Project project = method.getProject();
final JVMElementFactory factory;
if (target != null) {
factory = JVMElementFactories.getFactory(target.getLanguage(), method.getProject());
}
else {
factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
}
public static PsiMethod substituteGenericMethod(@NotNull PsiMethod sourceMethod,
@NotNull PsiSubstitutor substitutor,
@Nullable PsiElement target) {
final Project project = sourceMethod.getProject();
final JVMElementFactory factory = getFactory(sourceMethod, target);
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
final Module module = target != null ? ModuleUtil.findModuleForPsiElement(target) : null;
final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null;
try {
PsiType returnType = method.getReturnType();
PsiMethod newMethod;
if (method.isConstructor()) {
newMethod = factory.createConstructor();
newMethod.setName(method.getName());
}
else {
final PsiType substitutedReturnType = substituteType(substitutor, returnType);
newMethod = factory.createMethod(method.getName(), substitutedReturnType instanceof PsiWildcardType ? TypeConversionUtil.erasure(substitutedReturnType): substitutedReturnType);
}
VisibilityUtil.setVisibility(newMethod.getModifierList(), VisibilityUtil.getVisibilityModifier(method.getModifierList()));
PsiElement navigationElement = method.getNavigationElement();
PsiDocComment docComment = ((PsiDocCommentOwner)navigationElement).getDocComment();
if (docComment != null) {
newMethod.addAfter(docComment, null);
}
final Module module = target != null ? ModuleUtil.findModuleForPsiElement(target) : null;
final GlobalSearchScope moduleScope = module != null ? GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) : null;
PsiParameter[] parameters = method.getParameterList().getParameters();
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
Map<PsiType,Pair<String,Integer>> m = new HashMap<PsiType, Pair<String,Integer>>();
for (int i = 0; i < parameters.length; i++) {
PsiParameter parameter = parameters[i];
final PsiType parameterType = parameter.getType();
PsiType substituted = substituteType(substitutor, parameterType);
@NonNls String paramName = parameter.getName();
boolean isBaseNameGenerated = true;
final boolean isSubstituted = substituted.equals(parameterType);
if (!isSubstituted && isBaseNameGenerated(codeStyleManager, TypeConversionUtil.erasure(parameterType), paramName)) {
isBaseNameGenerated = false;
}
if (paramName == null || isBaseNameGenerated && !isSubstituted && isBaseNameGenerated(codeStyleManager, parameterType, paramName)) {
Pair<String, Integer> pair = m.get(substituted);
if (pair != null) {
paramName = pair.first + pair.second;
m.put(substituted, Pair.create(pair.first, pair.second.intValue() + 1));
}
else {
String[] names = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, substituted).names;
if (names.length > 0) {
paramName = names[0];
} else paramName = "p" + i;
m.put(substituted, new Pair<String, Integer>(paramName, 1));
}
}
if (paramName == null) paramName = "p" + i;
PsiParameter newParameter = factory.createParameter(paramName, substituted);
if (parameter.getLanguage() == newParameter.getLanguage()) {
PsiModifierList modifierList = newParameter.getModifierList();
modifierList = (PsiModifierList)modifierList.replace(parameter.getModifierList());
if (parameter.getLanguage() == JavaLanguage.INSTANCE) {
processAnnotations(project, modifierList, moduleScope);
}
}
else {
GenerateConstructorHandler.copyModifierList(factory,parameter, newParameter);
}
newMethod.getParameterList().add(newParameter);
}
for (PsiTypeParameter typeParam : method.getTypeParameters()) {
final PsiElement copy = typeParam.copy();
final Map<PsiElement, PsiElement> replacementMap = new HashMap<PsiElement, PsiElement>();
copy.accept(new JavaRecursiveElementVisitor(){
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
final PsiElement resolve = reference.resolve();
if (resolve instanceof PsiTypeParameter) {
replacementMap.put(reference, factory.createReferenceElementByType((PsiClassType)substituteType(substitutor, factory.createType((PsiTypeParameter)resolve))));
}
}
});
newMethod.getTypeParameterList().add(RefactoringUtil.replaceElementsWithMap(copy, replacementMap));
}
PsiClassType[] thrownTypes = method.getThrowsList().getReferencedTypes();
for (PsiClassType thrownType : thrownTypes) {
newMethod.getThrowsList().add(factory.createReferenceElementByType((PsiClassType)substituteType(substitutor, thrownType)));
}
return newMethod;
final PsiMethod resultMethod = createMethod(factory, sourceMethod);
copyDocComment(resultMethod, sourceMethod);
copyModifiers(sourceMethod.getModifierList(), resultMethod.getModifierList());
final PsiSubstitutor collisionResolvedSubstitutor =
substituteTypeParameters(factory, codeStyleManager, target, sourceMethod.getTypeParameterList(), resultMethod.getTypeParameterList(), substitutor);
substituteReturnType(PsiManager.getInstance(project), resultMethod, sourceMethod.getReturnType(), collisionResolvedSubstitutor);
substituteParameters(project, factory, codeStyleManager, moduleScope, sourceMethod.getParameterList(), resultMethod.getParameterList(), collisionResolvedSubstitutor);
substituteThrows(factory, sourceMethod.getThrowsList(), resultMethod.getThrowsList(), collisionResolvedSubstitutor);
return resultMethod;
}
catch (IncorrectOperationException e) {
LOG.error(e);
return method;
return sourceMethod;
}
}
private static void copyModifiers(@NotNull PsiModifierList sourceModifierList,
@NotNull PsiModifierList targetModifierList) {
VisibilityUtil.setVisibility(targetModifierList, VisibilityUtil.getVisibilityModifier(sourceModifierList));
}
@NotNull
private static PsiSubstitutor substituteTypeParameters(@NotNull JVMElementFactory factory,
@NotNull JavaCodeStyleManager codeStyleManager,
@Nullable PsiElement target,
@Nullable PsiTypeParameterList sourceTypeParameterList,
@Nullable PsiTypeParameterList targetTypeParameterList,
@NotNull PsiSubstitutor substitutor) {
if (sourceTypeParameterList == null || targetTypeParameterList == null) {
return substitutor;
}
final Map<PsiTypeParameter, PsiType> substitutionMap = new HashMap<PsiTypeParameter, PsiType>(substitutor.getSubstitutionMap());
for (PsiTypeParameter typeParam : sourceTypeParameterList.getTypeParameters()) {
final PsiTypeParameter substitutedTypeParam = substituteTypeParameter(factory, typeParam, substitutor);
final PsiTypeParameter resolvedTypeParam = resolveTypeParametersCollision(factory, sourceTypeParameterList, target, substitutedTypeParam, substitutor);
targetTypeParameterList.add(resolvedTypeParam);
if (substitutedTypeParam != resolvedTypeParam) {
substitutionMap.put(typeParam, factory.createType(resolvedTypeParam));
}
}
return substitutionMap.isEmpty() ? substitutor : factory.createSubstitutor(substitutionMap);
}
@NotNull
private static PsiTypeParameter resolveTypeParametersCollision(@NotNull JVMElementFactory factory,
@NotNull PsiTypeParameterList sourceTypeParameterList,
@Nullable PsiElement target,
@NotNull PsiTypeParameter typeParam,
@NotNull PsiSubstitutor substitutor) {
for (PsiType type : substitutor.getSubstitutionMap().values()) {
if (type != null && Comparing.equal(type.getCanonicalText(), typeParam.getName())) {
final String newName = suggestUniqueTypeParameterName(typeParam.getName(), sourceTypeParameterList, PsiTreeUtil.getParentOfType(target, PsiClass.class, false));
final PsiTypeParameter newTypeParameter = factory.createTypeParameter(newName, typeParam.getSuperTypes());
substitutor.put(typeParam, factory.createType(newTypeParameter));
return newTypeParameter;
}
}
return typeParam;
}
@NotNull
private static String suggestUniqueTypeParameterName(@NonNls String baseName, @NotNull PsiTypeParameterList typeParameterList, @Nullable PsiClass targetClass) {
int i = 0;
while (true) {
final String newName = baseName + ++i;
if (checkUniqueTypeParameterName(newName, typeParameterList) && (targetClass == null || checkUniqueTypeParameterName(newName, targetClass.getTypeParameterList()))) {
return newName;
}
}
}
private static boolean checkUniqueTypeParameterName(@NonNls @NotNull String baseName, @Nullable PsiTypeParameterList typeParameterList) {
if (typeParameterList == null) return true;
for (PsiTypeParameter typeParameter : typeParameterList.getTypeParameters()) {
if (Comparing.equal(typeParameter.getName(), baseName)) {
return false;
}
}
return true;
}
@NotNull
private static PsiTypeParameter substituteTypeParameter(final @NotNull JVMElementFactory factory,
@NotNull PsiTypeParameter typeParameter,
final @NotNull PsiSubstitutor substitutor) {
final PsiElement copy = typeParameter.copy();
final Map<PsiElement, PsiElement> replacementMap = new HashMap<PsiElement, PsiElement>();
copy.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
final PsiElement resolve = reference.resolve();
if (resolve instanceof PsiTypeParameter) {
final PsiType type = factory.createType((PsiTypeParameter)resolve);
replacementMap.put(reference, factory.createReferenceElementByType((PsiClassType)substituteType(substitutor, type)));
}
}
});
return (PsiTypeParameter)RefactoringUtil.replaceElementsWithMap(copy, replacementMap);
}
private static void substituteParameters(@NotNull Project project,
@NotNull JVMElementFactory factory,
@NotNull JavaCodeStyleManager codeStyleManager,
@Nullable GlobalSearchScope moduleScope,
@NotNull PsiParameterList sourceParameterList,
@NotNull PsiParameterList targetParameterList,
@NotNull PsiSubstitutor substitutor) {
PsiParameter[] parameters = sourceParameterList.getParameters();
Map<PsiType, Pair<String, Integer>> m = new HashMap<PsiType, Pair<String, Integer>>();
for (int i = 0; i < parameters.length; i++) {
PsiParameter parameter = parameters[i];
final PsiType parameterType = parameter.getType();
final PsiType substituted = substituteType(substitutor, parameterType);
@NonNls String paramName = parameter.getName();
boolean isBaseNameGenerated = true;
final boolean isSubstituted = substituted.equals(parameterType);
if (!isSubstituted && isBaseNameGenerated(codeStyleManager, TypeConversionUtil.erasure(parameterType), paramName)) {
isBaseNameGenerated = false;
}
if (paramName == null || isBaseNameGenerated && !isSubstituted && isBaseNameGenerated(codeStyleManager, parameterType, paramName)) {
Pair<String, Integer> pair = m.get(substituted);
if (pair != null) {
paramName = pair.first + pair.second;
m.put(substituted, Pair.create(pair.first, pair.second.intValue() + 1));
}
else {
String[] names = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, substituted).names;
if (names.length > 0) {
paramName = names[0];
}
else {
paramName = "p" + i;
}
m.put(substituted, new Pair<String, Integer>(paramName, 1));
}
}
if (paramName == null) paramName = "p" + i;
final PsiParameter newParameter = factory.createParameter(paramName, substituted);
if (parameter.getLanguage() == newParameter.getLanguage()) {
PsiModifierList modifierList = newParameter.getModifierList();
modifierList = (PsiModifierList)modifierList.replace(parameter.getModifierList());
if (parameter.getLanguage() == JavaLanguage.INSTANCE) {
processAnnotations(project, modifierList, moduleScope);
}
}
else {
GenerateConstructorHandler.copyModifierList(factory, parameter, newParameter);
}
targetParameterList.add(newParameter);
}
}
private static void substituteThrows(@NotNull JVMElementFactory factory,
@NotNull PsiReferenceList sourceThrowsList,
@NotNull PsiReferenceList targetThrowsList,
@NotNull PsiSubstitutor substitutor) {
for (PsiClassType thrownType : sourceThrowsList.getReferencedTypes()) {
targetThrowsList.add(factory.createReferenceElementByType((PsiClassType)substituteType(substitutor, thrownType)));
}
}
private static void copyDocComment(PsiMethod source, PsiMethod target) {
final PsiElement navigationElement = source.getNavigationElement();
final PsiDocComment docComment = ((PsiDocCommentOwner)navigationElement).getDocComment();
if (docComment != null) {
target.addAfter(docComment, null);
}
}
@NotNull
private static PsiMethod createMethod(@NotNull JVMElementFactory factory,
@NotNull PsiMethod method) {
if (method.isConstructor()) {
return factory.createConstructor(method.getName());
}
return factory.createMethod(method.getName(), PsiType.VOID);
}
private static void substituteReturnType(@NotNull PsiManager manager,
@NotNull PsiMethod method,
@Nullable PsiType returnType,
@NotNull PsiSubstitutor substitutor) {
final PsiTypeElement returnTypeElement = method.getReturnTypeElement();
if (returnTypeElement == null || returnType == null) {
return;
}
final PsiType substitutedReturnType = substituteType(substitutor, returnType);
returnTypeElement.replace(new LightTypeElement(manager, substitutedReturnType instanceof PsiWildcardType ? TypeConversionUtil.erasure(substitutedReturnType) : substitutedReturnType));
}
@NotNull
private static JVMElementFactory getFactory(@NotNull PsiMethod method, @Nullable PsiElement target) {
if (target == null) {
return JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
}
return JVMElementFactories.getFactory(target.getLanguage(), method.getProject());
}
private static boolean isBaseNameGenerated(JavaCodeStyleManager codeStyleManager, PsiType parameterType, String paramName) {
final String[] baseSuggestions = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, parameterType).names;
boolean isBaseNameGenerated = false;
@@ -399,7 +513,7 @@ public class GenerateMembersUtil {
public static boolean shouldAddOverrideAnnotation(PsiElement context, boolean interfaceMethod) {
CodeStyleSettings style = CodeStyleSettingsManager.getSettings(context.getProject());
if (!style.INSERT_OVERRIDE_ANNOTATION) return false;
if (interfaceMethod) return PsiUtil.isLanguageLevel6OrHigher(context);
return PsiUtil.isLanguageLevel5OrHigher(context);
}
@@ -66,8 +66,11 @@ public class HighlightOverridingMethodsHandler extends HighlightUsagesHandlerBas
if (containingClass == null) continue;
for (PsiClass classToAnalyze : classes) {
if (InheritanceUtil.isInheritorOrSelf(classToAnalyze, containingClass, true)) {
addOccurrence(method.getNameIdentifier());
break;
PsiIdentifier identifier = method.getNameIdentifier();
if (identifier != null) {
addOccurrence(identifier);
break;
}
}
}
}
@@ -28,15 +28,9 @@ import javax.swing.*;
/**
* @author Danila Ponomarenko
*/
public abstract class BaseRunRefactoringAction<T extends RefactoringActionHandler> implements IntentionAction, Iconable, LowPriorityAction {
public abstract class BaseRunRefactoringAction implements IntentionAction, Iconable, LowPriorityAction {
public static final Icon REFACTORING_BULB = AllIcons.Actions.RefactoringBulb;
@NotNull
@Override
public final String getFamilyName() {
return CodeInsightBundle.message("intention.refactoring.family");
}
@Override
public final boolean startInWriteAction() {
return false;
@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author Danila Ponomarenko
*/
public class EncapsulateFieldAction extends BaseRunRefactoringAction<EncapsulateFieldsHandler> {
public class EncapsulateFieldAction extends BaseRunRefactoringAction {
@NotNull
@Override
@@ -36,6 +36,12 @@ public class EncapsulateFieldAction extends BaseRunRefactoringAction<Encapsulate
return CodeInsightBundle.message("intention.encapsulate.field.text");
}
@NotNull
@Override
public final String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
final PsiField field = getField(getElement(editor, file));
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author Danila Ponomarenko
*/
public class IntroduceVariableAction extends BaseRunRefactoringAction<IntroduceVariableHandler> {
public class IntroduceVariableIntentionAction extends BaseRunRefactoringAction {
@NotNull
@Override
@@ -37,6 +37,12 @@ public class IntroduceVariableAction extends BaseRunRefactoringAction<IntroduceV
return CodeInsightBundle.message("intention.introduce.variable.text");
}
@NotNull
@Override
public String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
final PsiElement element = getElement(editor, file);
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
* User: anna
* Date: 9/5/11
*/
public class RunRefactoringAction extends BaseRunRefactoringAction<RefactoringActionHandler> {
public class RunRefactoringAction extends BaseRunRefactoringAction {
private final RefactoringActionHandler myHandler;
private final String myCommandName;
@@ -41,6 +41,12 @@ public class RunRefactoringAction extends BaseRunRefactoringAction<RefactoringAc
return myCommandName;
}
@NotNull
@Override
public final String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
@@ -34,8 +34,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryUtil;
import com.intellij.openapi.ui.DialogWrapper;
@@ -79,6 +78,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
scope.accept(new PsiElementVisitor() {
private int myFileCount = 0;
final private Set<Module> processed = new HashSet<Module>();
@Override
public void visitFile(PsiFile file) {
myFileCount++;
@@ -94,7 +94,8 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
if (module != null && !processed.contains(module)) {
processed.add(module);
if (JavaPsiFacade.getInstance(project)
.findClass(NullableNotNullManager.getInstance(project).getDefaultNullable(), GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)) == null) {
.findClass(NullableNotNullManager.getInstance(project).getDefaultNullable(),
GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)) == null) {
modulesWithoutAnnotations.add(module);
}
if (PsiUtil.getLanguageLevel(file).compareTo(LanguageLevel.JDK_1_5) < 0) {
@@ -104,13 +105,17 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
}
});
}
}, "Check applicability...", true, project)) return;
}, "Check applicability...", true, project)) {
return;
}
if (!modulesWithLL.isEmpty()) {
Messages.showErrorDialog(project, "Infer Nullity Annotations requires the project language level be set to 1.5 or greater.", INFER_NULLITY_ANNOTATIONS);
Messages.showErrorDialog(project, "Infer Nullity Annotations requires the project language level be set to 1.5 or greater.",
INFER_NULLITY_ANNOTATIONS);
return;
}
if (!modulesWithoutAnnotations.isEmpty()) {
final Library annotationsLib = LibraryUtil.findLibraryByClass(NullableNotNullManager.getInstance(project).getDefaultNullable(), project);
final Library annotationsLib =
LibraryUtil.findLibraryByClass(NullableNotNullManager.getInstance(project).getDefaultNullable(), project);
if (annotationsLib != null) {
String message = "Module" + (modulesWithoutAnnotations.size() == 1 ? " " : "s ");
message += StringUtil.join(modulesWithoutAnnotations, new Function<Module, String>() {
@@ -120,25 +125,27 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
}
}, ", ");
message += (modulesWithoutAnnotations.size() == 1 ? " doesn't" : " don't");
message += " refer to the existing '" + annotationsLib.getName() + "' library with IDEA nullity annotations. Would you like to add the dependenc";
message += (modulesWithoutAnnotations.size() == 1 ? "y" : "ies")+ " now?";
if (Messages.showOkCancelDialog(project, message, INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) == DialogWrapper.OK_EXIT_CODE) {
message += " refer to the existing '" +
annotationsLib.getName() +
"' library with IDEA nullity annotations. Would you like to add the dependenc";
message += (modulesWithoutAnnotations.size() == 1 ? "y" : "ies") + " now?";
if (Messages.showOkCancelDialog(project, message, INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) ==
DialogWrapper.OK_EXIT_CODE) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
for (Module module : modulesWithoutAnnotations) {
final ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(module).getModifiableModel();
modifiableModel.addLibraryEntry(annotationsLib);
modifiableModel.commit();
ModuleRootModificationUtil.addDependency(module, annotationsLib);
}
}
});
}
} else if (Messages.showOkCancelDialog(project, "Infer Nullity Annotations requires that the nullity annotations" +
" be available in all your project sources.\n\nYou will need to add annotations.jar as a library. " +
"It is possible to configure custom jar in e.g. Constant Conditions & Exceptions inspection or use JetBrains annotations available in installation. " +
" The IDEA nullity annotations are freely usable and redistributable under the Apache 2.0 license. Would you like to do it now?",
INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) == DialogWrapper.OK_EXIT_CODE) {
}
else if (Messages.showOkCancelDialog(project, "Infer Nullity Annotations requires that the nullity annotations" +
" be available in all your project sources.\n\nYou will need to add annotations.jar as a library. " +
"It is possible to configure custom jar in e.g. Constant Conditions & Exceptions inspection or use JetBrains annotations available in installation. " +
" The IDEA nullity annotations are freely usable and redistributable under the Apache 2.0 license. Would you like to do it now?",
INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) == DialogWrapper.OK_EXIT_CODE) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
final LocateLibraryDialog dialog =
@@ -169,6 +176,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
public void run() {
scope.accept(new PsiElementVisitor() {
int myFileCount = 0;
@Override
public void visitFile(final PsiFile file) {
myFileCount++;
@@ -189,7 +197,9 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
}
});
}
}, INFER_NULLITY_ANNOTATIONS, true, project)) return;
}, INFER_NULLITY_ANNOTATIONS, true, project)) {
return;
}
final Runnable applyRunnable = new Runnable() {
@Override
@@ -18,6 +18,7 @@ package com.intellij.ide.structureView.impl.java;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.light.LightElement;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -77,7 +78,10 @@ public class JavaClassTreeElement extends JavaClassTreeElementBase<PsiClass> {
private static void addPhysicalElements(PsiElement[] elements, LinkedHashSet<PsiElement> to) {
for (PsiElement element : elements) {
to.add(PsiImplUtil.handleMirror(element));
PsiElement mirror = PsiImplUtil.handleMirror(element);
if (!(mirror instanceof LightElement)) {
to.add(mirror);
}
}
}
@@ -25,6 +25,7 @@ import com.intellij.refactoring.ui.JavaCodeFragmentTableCellEditor;
import com.intellij.refactoring.ui.RefactoringDialog;
import com.intellij.refactoring.ui.StringTableCellEditor;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.ui.*;
import com.intellij.ui.table.JBTable;
import com.intellij.usageView.UsageViewUtil;
@@ -39,7 +40,9 @@ import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author dsl
@@ -153,10 +156,19 @@ public class ChangeClassSignatureDialog extends RefactoringDialog {
}
private String validateAndCommitData() {
final PsiTypeParameter[] parameters = myClass.getTypeParameters();
final Map<String, TypeParameterInfo> infos = new HashMap<String, TypeParameterInfo>();
for (final TypeParameterInfo info : myTypeParameterInfos) {
if (!info.isForExistingParameter() && !JavaPsiFacade.getInstance(myClass.getProject()).getNameHelper().isIdentifier(info.getNewName())) {
if (!info.isForExistingParameter() &&
!JavaPsiFacade.getInstance(myClass.getProject()).getNameHelper().isIdentifier(info.getNewName())) {
return RefactoringBundle.message("error.wrong.name.input", info.getNewName());
}
final String newName = info.isForExistingParameter() ? parameters[info.getOldParameterIndex()].getName() : info.getNewName();
TypeParameterInfo existing = infos.get(newName);
if (existing != null) {
return myClass.getName() + " already contains type parameter " + newName;
}
infos.put(newName, info);
}
LOG.assertTrue(myTypeCodeFragments.size() == myTypeParameterInfos.size());
for (int i = 0; i < myTypeCodeFragments.size(); i++) {
@@ -19,16 +19,19 @@ import com.intellij.history.LocalHistory;
import com.intellij.history.LocalHistoryAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.changeSignature.ChangeSignatureUtil;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -62,6 +65,23 @@ public class ChangeClassSignatureProcessor extends BaseRefactoringProcessor {
return new ChangeClassSigntaureViewDescriptor(myClass);
}
@Override
protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
final PsiTypeParameter[] parameters = myClass.getTypeParameters();
final Map<String, TypeParameterInfo> infos = new HashMap<String, TypeParameterInfo>();
for (TypeParameterInfo info : myNewSignature) {
final String newName = info.isForExistingParameter() ? parameters[info.getOldParameterIndex()].getName() : info.getNewName();
TypeParameterInfo existing = infos.get(newName);
if (existing != null) {
conflicts.putValue(myClass, RefactoringUIUtil.getDescription(myClass, false) + " already contains type parameter " + newName);
}
infos.put(newName, info);
}
return showConflicts(conflicts, refUsages.get());
}
@NotNull
protected UsageInfo[] findUsages() {
GlobalSearchScope projectScope = GlobalSearchScope.projectScope(myProject);
@@ -365,6 +365,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
final PsiReferenceExpression refExpr = PsiTreeUtil.getParentOfType(toBeExpression.findElementAt(refIdx[0]), PsiReferenceExpression.class);
assert refExpr != null;
if (toBeExpression == refExpr && refIdx[0] > 0) {
return null;
}
if (ReplaceExpressionUtil.isNeedParenthesis(refExpr.getNode(), tempExpr.getNode())) {
tempExpr.putCopyableUserData(NEED_PARENTHESIS, Boolean.TRUE);
return tempExpr;
@@ -220,10 +220,7 @@ public class MakeClassStaticProcessor extends MakeMethodOrClassStaticProcessor<P
element.replace(newRef);
}
}
else if (element instanceof PsiThisExpression && mySettings.isMakeClassParameter()) {
element.replace(factory.createExpressionFromText(convertToFieldName(mySettings.getClassParameterName()), null));
}
else if (element instanceof PsiSuperExpression && mySettings.isMakeClassParameter()) {
else if (mySettings.isMakeClassParameter() && (element instanceof PsiThisExpression || element instanceof PsiSuperExpression)) {
element.replace(factory.createExpressionFromText(convertToFieldName(mySettings.getClassParameterName()), null));
}
else if (element instanceof PsiNewExpression && mySettings.isMakeClassParameter()) {
@@ -34,7 +34,9 @@ import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.refactoring.util.ConflictsUtil;
import com.intellij.refactoring.util.MoveRenameUsageInfo;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.ArrayUtil;
@@ -153,6 +155,22 @@ public class RenameJavaClassProcessor extends RenamePsiElementProcessor {
}
}
findSubmemberHidesMemberCollisions(aClass, newName, result);
if (aClass instanceof PsiTypeParameter) {
final PsiTypeParameterListOwner owner = ((PsiTypeParameter)aClass).getOwner();
if (owner != null) {
for (PsiTypeParameter typeParameter : owner.getTypeParameters()) {
if (Comparing.equal(newName, typeParameter.getName())) {
result.add(new UnresolvableCollisionUsageInfo(aClass, typeParameter) {
@Override
public String getDescription() {
return "There is already type parameter in " + RefactoringUIUtil.getDescription(aClass, false) + " with name " + newName;
}
});
}
}
}
}
}
public static void findSubmemberHidesMemberCollisions(final PsiClass aClass, final String newName, final List<UsageInfo> result) {