Merge branch 'master' into upsource-master

Conflicts:
	java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.java
	java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertColorRepresentationTest.java
	jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
	jps/model/src/org/jetbrains/ether/dependencyView/IntIntMultiMaplet.java
	jps/model/src/org/jetbrains/ether/dependencyView/IntObjectMultiMaplet.java
	jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java
	platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java
	platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
	platform/platform-impl/src/com/intellij/featureStatistics/actions/ShowFeatureUsageStatisticsDialog.java
	platform/util/src/com/intellij/util/CommonProcessors.java
	plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
	plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy
	plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java
This commit is contained in:
Evgeny Pasynkov
2012-06-26 18:13:46 +02:00
146 changed files with 2590 additions and 1176 deletions
@@ -136,7 +136,7 @@ public class ExpectedTypesProvider {
public static PsiType[] processExpectedTypes(@NotNull ExpectedTypeInfo[] infos,
@NotNull PsiTypeVisitor<PsiType> visitor, @NotNull Project project) {
Set<PsiType> set = new LinkedHashSet<PsiType>();
LinkedHashSet<PsiType> set = new LinkedHashSet<PsiType>();
for (ExpectedTypeInfo info : infos) {
ExpectedTypeInfoImpl infoImpl = (ExpectedTypeInfoImpl)info;
@@ -85,7 +85,7 @@ public class JavaInheritorsGetter extends CompletionProvider<CompletionParameter
for (final PsiType type : ExpectedTypesGetter.extractTypes(infos, true)) {
if (type instanceof PsiArrayType) {
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), identifierCopy);
final LookupItem item = PsiTypeLookupItem.createLookupItem(TypeConversionUtil.erasure(type), identifierCopy);
if (item.getObject() instanceof PsiClass) {
JavaCompletionUtil.setShowFQN(item);
}
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.impl.analysis;
import com.google.common.collect.Lists;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
@@ -53,7 +53,8 @@ public class GenericsHighlightUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil");
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
private GenericsHighlightUtil() {}
private GenericsHighlightUtil() {
}
public static HighlightInfo checkInferredTypeArguments(PsiMethod genericMethod,
PsiMethodCallExpression call,
@@ -66,7 +67,7 @@ public class GenericsHighlightUtil {
PsiClassType[] extendsTypes = typeParameter.getExtendsListTypes();
for (PsiClassType type : extendsTypes) {
PsiType extendsType = substitutor.substitute(type);
if (substituted instanceof PsiWildcardType && TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(((PsiWildcardType)substituted).getExtendsBound()))){
if (substituted instanceof PsiWildcardType && TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(((PsiWildcardType)substituted).getExtendsBound()))) {
PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound();
if (extendsBound instanceof PsiClassType) {
PsiType[] parameters = ((PsiClassType)extendsBound).getParameters();
@@ -148,7 +149,8 @@ public class GenericsHighlightUtil {
if (PsiTreeUtil.getParentOfType(referenceParameterList, PsiCall.class) != null &&
PsiUtil.isLanguageLevel7OrHigher(referenceParameterList)) {
description = null;
} else {
}
else {
description = JavaErrorMessages.message(
"generics.type.or.method.does.not.have.type.parameters",
typeParameterListOwnerCategoryDescription(typeParameterListOwner),
@@ -157,9 +159,7 @@ public class GenericsHighlightUtil {
}
}
else {
description = JavaErrorMessages.message(
"generics.wrong.number.of.type.arguments", refParametersNum, targetParametersNum
);
description = JavaErrorMessages.message("generics.wrong.number.of.type.arguments", refParametersNum, targetParametersNum);
}
if (description != null) {
@@ -170,7 +170,10 @@ public class GenericsHighlightUtil {
PsiElement variable = pparent.getParent();
if (variable instanceof PsiVariable) {
if (targetParametersNum == 0) {
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveTypeArgumentsFix(variable), null);
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveTypeArgumentsFix(variable));
}
if (typeParameterListOwner instanceof PsiClass) {
QuickFixAction.registerQuickFixAction(highlightInfo, new ChangeClassSignatureFromUsageFix((PsiClass)typeParameterListOwner, referenceParameterList));
}
VariableParameterizedTypeFix.registerIntentions(highlightInfo, (PsiVariable)variable, referenceParameterList);
}
@@ -186,10 +189,11 @@ public class GenericsHighlightUtil {
final PsiType[] types = inferenceResult.getTypes();
for (int i = 0; i < typeParameters.length; i++) {
final PsiType type = types[i];
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, type, referenceElements[0]);
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, type, referenceElements[0]);
if (highlightInfo != null) return highlightInfo;
}
} else {
}
else {
for (int i = 0; i < typeParameters.length; i++) {
final PsiTypeElement typeElement = referenceElements[i];
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, typeElement.getType(), typeElement);
@@ -243,9 +247,10 @@ public class GenericsHighlightUtil {
final PsiType type,
final PsiElement typeElement2Highlight) {
final PsiClass referenceClass;
if (type instanceof PsiClassType){
if (type instanceof PsiClassType) {
referenceClass = ((PsiClassType)type).resolve();
} else {
}
else {
referenceClass = null;
}
final PsiType psiType = substitutor.substitute(classParameter);
@@ -314,7 +319,8 @@ public class GenericsHighlightUtil {
boundBound = ((PsiWildcardType)bound).isSuper()
? ((PsiWildcardType)bound).getSuperBound()
: ((PsiWildcardType)bound).getExtendsBound();
} else {
}
else {
return false;
}
}
@@ -335,10 +341,12 @@ public class GenericsHighlightUtil {
? ((PsiWildcardType)bound).getExtendsBound()
: ((PsiWildcardType)bound).getSuperBound();
return !TypeConversionUtil.isAssignable(boundBound, type, allowUncheckedConversion);
} else {
}
else {
return true;
}
} else {
}
else {
return !TypeConversionUtil.isAssignable(bound, type, allowUncheckedConversion);
}
}
@@ -349,7 +357,7 @@ public class GenericsHighlightUtil {
final PsiClass classType = ((PsiClassType)type).resolve();
if (classType != null) {
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(classType)) {
allowUncheckedConversions &= parameter.getExtendsListTypes().length == 0;
allowUncheckedConversions &= parameter.getExtendsListTypes().length == 0;
}
}
}
@@ -404,13 +412,14 @@ public class GenericsHighlightUtil {
IntentionAction fix = QUICK_FIX_FACTORY.createExtendsListFix(aClass, type, false);
QuickFixAction.registerQuickFixAction(errorResult, fix, null);
}
if (errorResult == null && JavaVersionService.getInstance().isAtLeast(referenceList, JavaSdkVersion.JDK_1_7) &&
if (errorResult == null && JavaVersionService.getInstance().isAtLeast(referenceList, JavaSdkVersion.JDK_1_7) &&
referenceElements.length > 1) {
//todo suppress erased methods which come from the same class
return checkOverrideEquivalentMethods(aClass);
}
return errorResult;
}
public static HighlightInfo checkInterfaceMultipleInheritance(PsiClass aClass) {
if (aClass instanceof PsiTypeParameter) return null;
final PsiClassType[] types = aClass.getSuperTypes();
@@ -466,7 +475,7 @@ public class GenericsHighlightUtil {
PsiManager manager = aClass.getManager();
Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods =
new THashMap<MethodSignature, MethodSignatureBackedByPsiMethod>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
for (HierarchicalMethodSignature signature : signaturesWithSupers) {
HighlightInfo info = checkSameErasureNotSubSignatureInner(signature, manager, aClass, sameErasureMethods);
if (info != null) return info;
@@ -529,7 +538,8 @@ public class GenericsHighlightUtil {
if (checkEqualsSuper && atLeast17) {
if (retErasure1 != null && retErasure2 != null) {
differentReturnTypeErasure = !TypeConversionUtil.isAssignable(retErasure1, retErasure2);
} else {
}
else {
differentReturnTypeErasure = !(retErasure1 == null && retErasure2 == null);
}
}
@@ -565,10 +575,10 @@ public class GenericsHighlightUtil {
private static HighlightInfo getSameErasureMessage(final boolean sameClass, final PsiMethod method, final PsiMethod superMethod,
TextRange textRange) {
@NonNls final String key = sameClass ? "generics.methods.have.same.erasure" :
method.hasModifierProperty(PsiModifier.STATIC) ?
"generics.methods.have.same.erasure.hide" :
"generics.methods.have.same.erasure.override";
@NonNls final String key = sameClass ? "generics.methods.have.same.erasure" :
method.hasModifierProperty(PsiModifier.STATIC) ?
"generics.methods.have.same.erasure.hide" :
"generics.methods.have.same.erasure.override";
String description = JavaErrorMessages.message(key, HighlightMethodUtil.createClashMethodMessage(method, superMethod, !sameClass));
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description);
}
@@ -650,7 +660,8 @@ public class GenericsHighlightUtil {
if (isRawToGeneric(lType, type)) return true;
}
return false;
} else if (lType instanceof PsiIntersectionType) {
}
else if (lType instanceof PsiIntersectionType) {
for (PsiType type : ((PsiIntersectionType)lType).getConjuncts()) {
if (isRawToGeneric(type, rType)) return true;
}
@@ -672,7 +683,9 @@ public class GenericsHighlightUtil {
PsiSubstitutor rSubstitutor = rResolveResult.getSubstitutor();
if (lClass == null || rClass == null) return false;
if (lClass instanceof PsiTypeParameter &&
!InheritanceUtil.isInheritorOrSelf(rClass, lClass, true)) return true;
!InheritanceUtil.isInheritorOrSelf(rClass, lClass, true)) {
return true;
}
if (!lClass.getManager().areElementsEquivalent(lClass, rClass)) {
if (lClass.isInheritor(rClass, true)) {
@@ -698,7 +711,7 @@ public class GenericsHighlightUtil {
PsiType rTypeArg = rSubstitutor.substituteWithBoundsPromotion(rParameter);
if (lTypeArg == null) continue;
if (rTypeArg == null) {
if (lTypeArg instanceof PsiWildcardType && ((PsiWildcardType) lTypeArg).getBound() == null) {
if (lTypeArg instanceof PsiWildcardType && ((PsiWildcardType)lTypeArg).getBound() == null) {
continue;
}
else {
@@ -922,7 +935,7 @@ public class GenericsHighlightUtil {
for (int i = 0; i < typeParameters.length; i++) {
final PsiTypeParameter typeParameter1 = typeParameters[i];
String name1 = typeParameter1.getName();
for (int j = i+1; j < typeParameters.length; j++) {
for (int j = i + 1; j < typeParameters.length; j++) {
final PsiTypeParameter typeParameter2 = typeParameters[j];
String name2 = typeParameter2.getName();
if (Comparing.strEqual(name1, name2)) {
@@ -937,7 +950,7 @@ public class GenericsHighlightUtil {
@Nullable
public static Collection<HighlightInfo> checkCatchParameterIsClass(PsiParameter parameter) {
if (!(parameter.getDeclarationScope() instanceof PsiCatchSection)) return null;
final Collection<HighlightInfo> result = Lists.newArrayList();
final Collection<HighlightInfo> result = CollectionFactory.arrayList();
final List<PsiTypeElement> typeElements = PsiUtil.getParameterTypeElements(parameter);
for (PsiTypeElement typeElement : typeElements) {
@@ -975,12 +988,12 @@ public class GenericsHighlightUtil {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("illegal.generic.type.for.instanceof"));
}
}
final PsiType[] parameters = ref.getTypeParameters();
for (PsiType parameterType : parameters) {
if (parameterType != null &&
!(parameterType instanceof PsiWildcardType && ((PsiWildcardType)parameterType).getBound() == null)) {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("illegal.generic.type.for.instanceof"));
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("illegal.generic.type.for.instanceof"));
}
}
@@ -1057,7 +1070,6 @@ public class GenericsHighlightUtil {
}
LOG.assertTrue(varParameter.isVarArgs());
final PsiEllipsisType ellipsisType = (PsiEllipsisType)varParameter.getType();
final PsiType componentType = ellipsisType.getComponentType();
@@ -1099,14 +1111,15 @@ public class GenericsHighlightUtil {
return false;
}
}
} else if (lastArg instanceof PsiMethodCallExpression) {
}
else if (lastArg instanceof PsiMethodCallExpression) {
if (lastArg.getType() instanceof PsiArrayType) {
return false;
}
}
}
for (int i = parametersCount - 1; i < args.length; i++) {
if (!isReifiableType(resolveResult.getSubstitutor().substitute(args[i].getType()))){
if (!isReifiableType(resolveResult.getSubstitutor().substitute(args[i].getType()))) {
return true;
}
}
@@ -1156,7 +1169,8 @@ public class GenericsHighlightUtil {
}
static void checkEnumConstantForConstructorProblems(PsiEnumConstant enumConstant, final HighlightInfoHolder holder) {
PsiClass containingClass = enumConstant.getContainingClass(); if (enumConstant.getInitializingClass() == null) {
PsiClass containingClass = enumConstant.getContainingClass();
if (enumConstant.getInitializingClass() == null) {
HighlightInfo highlightInfo = HighlightClassUtil.checkInstantiationOfAbstractClass(containingClass, enumConstant.getNameIdentifier());
if (highlightInfo != null) {
QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createImplementMethodsFix(enumConstant));
@@ -1233,8 +1247,9 @@ public class GenericsHighlightUtil {
PsiElement parent = refParamList.getParent();
if (parent instanceof PsiJavaCodeReferenceElement) {
resolveResult = ((PsiJavaCodeReferenceElement)parent).advancedResolve(false);
} else if (parent instanceof PsiCallExpression) {
resolveResult = ((PsiCallExpression)parent).resolveMethodGenerics();
}
else if (parent instanceof PsiCallExpression) {
resolveResult = ((PsiCallExpression)parent).resolveMethodGenerics();
}
if (resolveResult != null) {
PsiElement element = resolveResult.getElement();
@@ -1257,12 +1272,13 @@ public class GenericsHighlightUtil {
public static HighlightInfo checkCannotInheritFromEnum(PsiClass superClass, PsiElement elementToHighlight) {
HighlightInfo errorResult = null;
if (Comparing.strEqual("java.lang.Enum",superClass.getQualifiedName())) {
if (Comparing.strEqual("java.lang.Enum", superClass.getQualifiedName())) {
String message = JavaErrorMessages.message("classes.extends.enum");
errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, elementToHighlight, message);
}
return errorResult;
}
public static HighlightInfo checkGenericCannotExtendException(PsiReferenceList list) {
PsiElement parent = list.getParent();
if (!(parent instanceof PsiClass)) return null;
@@ -0,0 +1,158 @@
/*
* 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.
*/
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.refactoring.changeClassSignature.ChangeClassSignatureDialog;
import com.intellij.refactoring.changeClassSignature.TypeParameterInfo;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* @author Danila Ponomarenko
*/
public class ChangeClassSignatureFromUsageFix extends BaseIntentionAction {
private final PsiClass myClass;
private final PsiReferenceParameterList myParameterList;
public ChangeClassSignatureFromUsageFix(@NotNull PsiClass aClass,
@NotNull PsiReferenceParameterList parameterList) {
myClass = aClass;
myParameterList = parameterList;
}
@NotNull
@Override
public String getFamilyName() {
return QuickFixBundle.message("change.class.signature.family");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!myClass.isValid() || !myParameterList.isValid()) {
return false;
}
if (myClass.getTypeParameters().length >= myParameterList.getTypeArguments().length) {
return false;
}
final PsiTypeParameterList classTypeParameterList = myClass.getTypeParameterList();
if (classTypeParameterList == null) {
return false;
}
setText(QuickFixBundle.message("change.class.signature.text", myClass.getName(), myParameterList.getText()));
return true;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
final PsiTypeParameterList classTypeParameterList = myClass.getTypeParameterList();
if (classTypeParameterList == null) {
return;
}
ChangeClassSignatureDialog dialog = new ChangeClassSignatureDialog(
myClass,
createTypeParameters(
JavaCodeFragmentFactory.getInstance(project),
Arrays.asList(classTypeParameterList.getTypeParameters()),
Arrays.asList(myParameterList.getTypeParameterElements())
),
false
);
dialog.show();
}
@NotNull
private static Map<TypeParameterInfo, PsiTypeCodeFragment> createTypeParameters(@NotNull JavaCodeFragmentFactory factory,
@NotNull List<PsiTypeParameter> classTypeParameters,
@NotNull List<PsiTypeElement> typeElements) {
final LinkedHashMap<TypeParameterInfo, PsiTypeCodeFragment> result = new LinkedHashMap<TypeParameterInfo, PsiTypeCodeFragment>();
final TypeParameterNameSuggester suggester = new TypeParameterNameSuggester(classTypeParameters);
int listIndex = 0;
for (PsiTypeElement typeElement : typeElements) {
if (listIndex < classTypeParameters.size()) {
final PsiTypeParameter typeParameter = classTypeParameters.get(listIndex);
if (isAssignable(typeParameter, typeElement.getType())) {
result.put(new TypeParameterInfo(listIndex++), null);
continue;
}
}
final PsiClassType type = (PsiClassType)typeElement.getType();
result.put(new TypeParameterInfo(suggester.suggest(type), type), factory.createTypeCodeFragment(type.getClassName(), typeElement, true));
}
return result;
}
private static boolean isAssignable(@NotNull PsiTypeParameter typeParameter, @NotNull PsiType type) {
for (PsiClassType t : typeParameter.getExtendsListTypes()) {
if (!t.isAssignableFrom(type)) {
return false;
}
}
return true;
}
@Override
public boolean startInWriteAction() {
return false;
}
private static class TypeParameterNameSuggester {
private final Set<String> usedNames = new HashSet<String>();
public TypeParameterNameSuggester(@NotNull PsiTypeParameter... typeParameters) {
this(Arrays.asList(typeParameters));
}
public TypeParameterNameSuggester(@NotNull Collection<PsiTypeParameter> typeParameters) {
for (PsiTypeParameter p : typeParameters) {
usedNames.add(p.getName());
}
}
@NotNull
private String suggestUnusedName(@NotNull String name) {
String unusedName = name;
int i = 0;
while (true) {
if (usedNames.add(unusedName)) {
return unusedName;
}
unusedName = name + ++i;
}
}
@NotNull
public String suggest(@NotNull PsiClassType type) {
return suggestUnusedName(type.getClassName().substring(0, 1).toUpperCase());
}
}
}
@@ -73,7 +73,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction, HighP
private final boolean myChangeAllUsages;
private final int myMinUsagesNumberToShowDialog;
ParameterInfoImpl[] myNewParametersInfo;
private static final Logger LOG = Logger.getInstance("#" + ChangeMethodSignatureFromUsageFix.class.getName());
private static final Logger LOG = Logger.getInstance(ChangeMethodSignatureFromUsageFix.class);
ChangeMethodSignatureFromUsageFix(@NotNull PsiMethod targetMethod,
@NotNull PsiExpression[] expressions,
@@ -29,10 +29,13 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
/**
* @author Mike
*/
public class CreateFieldFromUsageFix extends CreateVarFromUsageFix {
public static boolean DEBUG = false;
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.CreateFieldFromUsageFix");
public CreateFieldFromUsageFix(PsiReferenceExpression referenceElement) {
@@ -71,6 +74,10 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix {
final PsiFile targetFile = targetClass.getContainingFile();
ExpectedTypeInfo[] expectedTypes = CreateFromUsageUtils.guessExpectedTypes(myReferenceExpression, false);
if (DEBUG) {
System.out.println("CreateFieldFromUsageFix.invokeImpl");
System.out.println("expectedTypes = " + Arrays.toString(expectedTypes));
}
String fieldName = myReferenceExpression.getReferenceName();
assert fieldName != null;
@@ -623,6 +623,7 @@ public class CreateFromUsageUtils {
getExpectedInformation(expression, typesList, expectedMethodNames, expectedFieldNames);
if (typesList.size() == 1 && (!expectedFieldNames.isEmpty() || !expectedMethodNames.isEmpty())) {
ExpectedTypeInfo[] infos = typesList.get(0);
if (infos.length == 1 && infos[0].getKind() == ExpectedTypeInfo.TYPE_OR_SUBTYPE &&
@@ -773,16 +774,34 @@ public class CreateFromUsageUtils {
public int compare(final PsiMember m1, final PsiMember m2) {
ProgressManager.checkCanceled();
int result = JavaStatisticsManager.createInfo(null, m2).getUseCount() - JavaStatisticsManager.createInfo(null, m1).getUseCount();
if (CreateFieldFromUsageFix.DEBUG) {
System.out.println("CreateFromUsageUtils.compare");
System.out.println("m1 = " + m1);
System.out.println("m2 = " + m2);
System.out.println("result = " + result);
}
if (result != 0) return result;
final PsiClass aClass = m1.getContainingClass();
final PsiClass bClass = m2.getContainingClass();
if (aClass == null || bClass == null) return 0;
if (CreateFieldFromUsageFix.DEBUG) {
System.out.println("aClass = " + aClass);
System.out.println("bClass = " + bClass);
}
result = JavaStatisticsManager.createInfo(null, bClass).getUseCount() - JavaStatisticsManager.createInfo(null, aClass).getUseCount();
if (CreateFieldFromUsageFix.DEBUG) {
System.out.println("result2 = " + result);
}
if (result != 0) return result;
WeighingComparable<PsiElement,ProximityLocation> proximity1 = PsiProximityComparator.getProximity(m1, expression);
WeighingComparable<PsiElement,ProximityLocation> proximity2 = PsiProximityComparator.getProximity(m2, expression);
if (proximity1 != null && proximity2 != null) {
if (CreateFieldFromUsageFix.DEBUG) {
System.out.println("proximity1 = " + proximity1);
System.out.println("proximity2 = " + proximity2);
}
return proximity2.compareTo(proximity1);
}
@@ -797,6 +816,11 @@ public class CreateFromUsageUtils {
ProgressManager.checkCanceled();
PsiClass aClass = member.getContainingClass();
if (aClass instanceof PsiAnonymousClass || aClass == null) continue;
if (CreateFieldFromUsageFix.DEBUG) {
System.out.println("CreateFromUsageUtils.addMemberInfo");
System.out.println("member = " + member);
System.out.println("aClass = " + aClass);
}
if (facade.getResolveHelper().isAccessible(member, expression, null)) {
PsiClassType type;
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.NotNull;
* @author ven
*/
public abstract class MethodArgumentFix implements IntentionAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.MethodArgumentFix");
private static final Logger LOG = Logger.getInstance(MethodArgumentFix.class);
protected final PsiExpressionList myArgList;
protected final int myIndex;
@@ -0,0 +1,80 @@
/*
* 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.
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author Danila Ponomarenko
*/
public abstract class BaseColorIntentionAction extends PsiElementBaseIntentionAction implements HighPriorityAction {
protected static final String JAVA_AWT_COLOR = "java.awt.Color";
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (!psiElement().inside(psiElement(PsiNewExpression.class)).accepts(element)) {
return false;
}
final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false);
if (expression == null) {
return false;
}
return isJavaAwtColor(expression.getClassOrAnonymousClassReference()) && isValueArguments(expression.getArgumentList());
}
private static boolean isJavaAwtColor(@Nullable PsiJavaCodeReferenceElement ref) {
if (ref == null) {
return false;
}
final PsiReference reference = ref.getReference();
if (reference == null) {
return false;
}
final PsiElement psiElement = reference.resolve();
if (psiElement instanceof PsiClass && JAVA_AWT_COLOR.equals(((PsiClass)psiElement).getQualifiedName())) {
return true;
}
return false;
}
private static boolean isValueArguments(@Nullable PsiExpressionList arguments) {
if (arguments == null) {
return false;
}
for (PsiExpression argument : arguments.getExpressions()) {
if (argument instanceof PsiReferenceExpression) {
return false;
}
}
return true;
}
}
@@ -46,9 +46,7 @@ import static com.intellij.patterns.PlatformPatterns.psiElement;
* @author spleaner
* @author Konstantin Bulenkov
*/
public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction {
private static final String JAVA_AWT_COLOR = "java.awt.Color";
public class ColorChooserIntentionAction extends BaseColorIntentionAction {
private static final PsiMethodPattern DECODE_METHOD = PsiJavaPatterns.psiMethod()
.definedInClass(JAVA_AWT_COLOR)
.withName("decode");
@@ -64,20 +62,7 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction {
@Override
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
// new Color(...)
if (psiElement().inside(psiElement(PsiNewExpression.class)).accepts(element)) {
final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false);
if (expression != null) {
final PsiJavaCodeReferenceElement ref = PsiTreeUtil.getChildOfType(expression, PsiJavaCodeReferenceElement.class);
if (isJavaAwtColor(ref)) return true;
}
}
// Color.decode("...")
if (isInsideDecodeOrGetColorMethod(element)) {
return true;
}
return false;
return super.isAvailable(project, editor, element) || isInsideDecodeOrGetColorMethod(element);
}
public static boolean isInsideDecodeOrGetColorMethod(PsiElement element) {
@@ -85,24 +70,10 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction {
element = element.getParent();
}
return PsiJavaPatterns.psiExpression().methodCallParameter(0, DECODE_METHOD).accepts(element)
||
return PsiJavaPatterns.psiExpression().methodCallParameter(0, DECODE_METHOD).accepts(element) ||
PsiJavaPatterns.psiExpression().methodCallParameter(0, GET_COLOR_METHOD).accepts(element);
}
private static boolean isJavaAwtColor(final PsiJavaCodeReferenceElement ref) {
if (ref != null) {
final PsiReference reference = ref.getReference();
if (reference != null) {
final PsiElement psiElement = reference.resolve();
if (psiElement instanceof PsiClass && JAVA_AWT_COLOR.equals(((PsiClass)psiElement).getQualifiedName())) {
return true;
}
}
}
return false;
}
@Override
@NotNull
public String getFamilyName() {
@@ -116,7 +87,8 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction {
final JComponent editorComponent = editor.getComponent();
if (isInsideDecodeOrGetColorMethod(element)) {
invokeForMethodParam(editorComponent, element);
} else {
}
else {
invokeForConstructor(editorComponent, element);
}
}
@@ -139,9 +111,9 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction {
if (color == null) return;
final int rgb = color.getRGB() - ((255 & 0xFF) << 24);
if (color != null && rgb != oldColor.getRGB()) {
final String newText = radix == 16 ? hexPrefix + String.format("%6s" ,Integer.toHexString(rgb)).replace(' ', '0')
: radix == 8 ? "0" + Integer.toOctalString(rgb)
: Integer.toString(rgb);
final String newText = radix == 16 ? hexPrefix + String.format("%6s", Integer.toHexString(rgb)).replace(' ', '0')
: radix == 8 ? "0" + Integer.toOctalString(rgb)
: Integer.toString(rgb);
final PsiManager manager = literal.getManager();
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiExpression newLiteral = factory.createExpressionFromText("\"" + newText + "\"", literal);
@@ -221,12 +193,12 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction {
final PsiManager manager = expression.getManager();
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiExpression newCall = factory.createExpressionFromText(
"new " + JAVA_AWT_COLOR +"("
+ color.getRed() + ", "
+ color.getGreen() + ", "
+ color.getBlue()
+ (color.getAlpha() < 255 ? ", " + color.getAlpha() : "")
+")", expression);
"new " + JAVA_AWT_COLOR + "("
+ color.getRed() + ", "
+ color.getGreen() + ", "
+ color.getBlue()
+ (color.getAlpha() < 255 ? ", " + color.getAlpha() : "")
+ ")", expression);
final PsiElement insertedElement = expression.replace(newCall);
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());
codeStyleManager.reformat(insertedElement);
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
@@ -38,7 +39,6 @@ public class ConvertAbsolutePathToRelativeIntentionAction extends BaseIntentionA
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset());
final FileReference fileReference = reference == null ? null : findFileReference(reference);
@@ -81,6 +81,8 @@ public class ConvertAbsolutePathToRelativeIntentionAction extends BaseIntentionA
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset());
final FileReference fileReference = reference == null ? null : findFileReference(reference);
if (fileReference != null) {
@@ -0,0 +1,226 @@
/*
* 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.
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Danila Ponomarenko
*/
public class ConvertColorRepresentationIntentionAction extends BaseColorIntentionAction {
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (!super.isAvailable(project, editor, element)) {
return false;
}
final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false);
if (expression == null) {
return false;
}
final PsiExpressionList arguments = expression.getArgumentList();
if (arguments == null) {
return false;
}
final PsiMethod constructor = expression.resolveConstructor();
if (constructor == null) {
return false;
}
final PsiExpressionList newArguments = createNewArguments(JavaPsiFacade.getElementFactory(project), constructor.getParameterList().getParameters(), arguments.getExpressions());
if (newArguments == null) {
return false;
}
setText(CodeInsightBundle.message("intention.convert.color.representation.text", newArguments.getText()));
return true;
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
if (!CodeInsightUtilBase.preparePsiElementForWrite(element)) return;
final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false);
if (expression == null) {
return;
}
final PsiExpressionList arguments = expression.getArgumentList();
if (arguments == null) {
return;
}
final PsiMethod constructor = expression.resolveConstructor();
if (constructor == null) {
return;
}
final PsiExpressionList newArguments = createNewArguments(
JavaPsiFacade.getElementFactory(project),
constructor.getParameterList().getParameters(),
arguments.getExpressions()
);
if (newArguments == null) {
return;
}
arguments.replace(newArguments);
}
@Nullable
private static PsiExpressionList createNewArguments(@NotNull PsiElementFactory factory,
@NotNull PsiParameter[] parameters,
@NotNull PsiExpression[] arguments) {
final String[] newValues = createArguments(parameters, arguments);
if (newValues == null) {
return null;
}
final PsiExpressionList result = ((PsiNewExpression)factory.createExpressionFromText("new Object()", parameters[0])).getArgumentList();
if (result == null) {
return null;
}
for (String value : newValues) {
result.add(factory.createExpressionFromText(value, parameters[0]));
}
return result;
}
@Nullable
private static String[] createArguments(@NotNull PsiParameter[] parameters,
@NotNull PsiExpression[] arguments) {
if (parameters.length != arguments.length) {
return null;
}
switch (parameters.length) {
default:
return null;
case 1:
return createArguments(arguments[0]);
case 2:
return createArguments(arguments[0], arguments[1]);
case 3:
return createArguments(arguments[0], arguments[1], arguments[2]);
case 4:
return createArguments(arguments[0], arguments[1], arguments[2], arguments[3]);
}
}
@Nullable
private static String[] createArguments(@NotNull PsiExpression rgbExpression) {
return createArguments(rgbExpression, 3);
}
@Nullable
private static String[] createArguments(@NotNull PsiExpression rgbExpression,
@NotNull PsiExpression hasAlphaExpression) {
final Boolean hasAlpha = computeBoolean(hasAlphaExpression);
if (hasAlpha == null) {
return null;
}
return hasAlpha ? createArguments(rgbExpression, 4) : createArguments(rgbExpression);
}
@Nullable
private static String[] createArguments(@NotNull PsiExpression rExpression,
@NotNull PsiExpression gExpression,
@NotNull PsiExpression bExpression) {
final Integer value = createInt(computeInteger(rExpression), computeInteger(gExpression), computeInteger(bExpression));
return value != null ? new String[]{"0x" + Integer.toHexString(value)} : null;
}
@Nullable
private static String[] createArguments(@NotNull PsiExpression rExpression,
@NotNull PsiExpression gExpression,
@NotNull PsiExpression bExpression,
@NotNull PsiExpression aExpression) {
final Integer value = createInt(computeInteger(rExpression), computeInteger(gExpression), computeInteger(bExpression), computeInteger(aExpression));
if (value == null) {
return null;
}
return new String[]{
"0x" + Integer.toHexString(value),
"true",
};
}
@Nullable
private static String[] createArguments(@NotNull PsiExpression rgbExpression,
int parts) {
final Integer rgb = computeInteger(rgbExpression);
if (rgb == null) {
return null;
}
final String[] result = new String[parts];
for (int i = 0; i < result.length; i++) {
result[result.length - i - 1] = String.valueOf(rgb >> (i * Byte.SIZE) & 0xFF);
}
return result;
}
@Nullable
private static Integer createInt(Integer... ints) {
int result = 0;
for (Integer i : ints) {
if (i == null) {
return null;
}
result = result << Byte.SIZE | (i & 0xFF);
}
return result;
}
@Nullable
public static Integer computeInteger(@NotNull PsiExpression expr) {
final Object result = compute(expr);
return result instanceof Integer ? (Integer)result : null;
}
@Nullable
public static Boolean computeBoolean(@NotNull PsiExpression expr) {
final Object result = compute(expr);
return result instanceof Boolean ? (Boolean)result : null;
}
@Nullable
private static Object compute(@NotNull PsiExpression expr) {
return JavaConstantExpressionEvaluator.computeConstantExpression(expr, true);
}
@NotNull
@Override
public String getFamilyName() {
return CodeInsightBundle.message("intention.convert.color.representation.family");
}
}
@@ -28,10 +28,9 @@ import com.intellij.psi.*;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class TypeExpression extends Expression {
private final Set<SmartTypePointer> myItems;
private final LinkedHashSet<SmartTypePointer> myItems;
public TypeExpression(final Project project, PsiType[] types) {
final SmartTypePointerManager manager = SmartTypePointerManager.getInstance(project);
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.completion.*;
import com.intellij.ide.highlighter.XmlLikeFileType;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.util.ClassConditionKey;
@@ -79,7 +80,11 @@ public class PsiTypeLookupItem extends LookupItem {
PsiElement position = context.getFile().findElementAt(context.getStartOffset());
assert position != null;
int genericsStart = context.getTailOffset();
context.getDocument().insertString(genericsStart, calcGenerics(position, context));
String generics = calcGenerics(position, context);
if (context.getFile().getFileType() instanceof XmlLikeFileType) {
generics = StringUtil.escapeXml(generics);
}
context.getDocument().insertString(genericsStart, generics);
JavaCompletionUtil.shortenReference(context.getFile(), genericsStart - 1);
int tail = context.getTailOffset();
@@ -34,6 +34,7 @@ import com.intellij.codeInspection.*;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.ex.BaseLocalInspectionTool;
import com.intellij.ide.DataManager;
import com.intellij.lang.ASTFactory;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -41,6 +42,8 @@ import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.codeStyle.CodeFormatterFacade;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
@@ -230,8 +233,11 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
else if (psiAnchor != null && !reportedAnchors.contains(psiAnchor) && !isCompileConstantInIfCondition(psiAnchor)) {
boolean evaluatesToTrue = trueSet.contains(instruction);
if (onTheLeftSideOfConditionalAssignemnt(psiAnchor)) {
holder.registerProblem(psiAnchor, InspectionsBundle.message("dataflow.message.pointless.assignment.expression",
Boolean.toString(evaluatesToTrue)));
holder.registerProblem(
psiAnchor,
InspectionsBundle.message("dataflow.message.pointless.assignment.expression", Boolean.toString(evaluatesToTrue)),
createSimplifyToAssignmentFix()
);
}
else {
boolean report = !(psiAnchor.getParent() instanceof PsiAssertStatement) || !DONT_REPORT_TRUE_ASSERT_STATEMENTS || !evaluatesToTrue;
@@ -370,6 +376,40 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
};
}
@NotNull
private static LocalQuickFix createSimplifyToAssignmentFix() {
return new LocalQuickFix() {
@NotNull
@Override
public String getName() {
return InspectionsBundle.message("inspection.data.flow.simplify.to.assignment.quickfix.name");
}
@NotNull
@Override
public String getFamilyName() {
return InspectionsBundle.message("inspection.data.flow.simplify.boolean.expression.quickfix");
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement psiElement = descriptor.getPsiElement();
if (psiElement == null) return;
final PsiAssignmentExpression assignmentExpression = PsiTreeUtil.getParentOfType(psiElement, PsiAssignmentExpression.class);
if (assignmentExpression == null) {
return;
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final String lExpressionText = assignmentExpression.getLExpression().getText();
final PsiExpression rExpression = assignmentExpression.getRExpression();
final String rExpressionText = rExpression != null ? rExpression.getText() : "";
assignmentExpression.replace(factory.createExpressionFromText(lExpressionText + " = " + rExpressionText, psiElement));
}
};
}
private static SimplifyBooleanExpressionFix createIntention(PsiElement element, boolean value) {
if (!(element instanceof PsiExpression)) return null;
final PsiExpression expression = (PsiExpression)element;
@@ -27,14 +27,15 @@ package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInspection.dataFlow.value.DfaTypeValue;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.psi.PsiPrimitiveType;
import com.intellij.psi.PsiVariable;
import com.intellij.codeInspection.nullable.NullableStuffInspection;
import com.intellij.psi.*;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class DfaVariableState implements Cloneable {
@@ -48,8 +49,36 @@ public class DfaVariableState implements Cloneable {
myVar = var;
myInstanceofValues = new HashSet<DfaTypeValue>();
myNotInstanceofValues = new HashSet<DfaTypeValue>();
myNullable = var != null && NullableNotNullManager.isNullable(var);
myVariableIsDeclaredNotNull = var != null && NullableNotNullManager.isNotNull(var);
myNullable = var != null && (NullableNotNullManager.isNullable(var) || isNullableInitialized(var, true));
myVariableIsDeclaredNotNull = var != null && (NullableNotNullManager.isNotNull(var) || isNullableInitialized(var, false));
}
private static boolean isNullableInitialized(PsiVariable var, boolean nullable) {
if (!var.hasModifierProperty(PsiModifier.FINAL) || !(var instanceof PsiField)) {
return false;
}
List<PsiExpression> initializers = NullableStuffInspection.findAllConstructorInitializers((PsiField)var);
if (!nullable && initializers.isEmpty()) {
return false;
}
for (PsiExpression expression : initializers) {
if (!(expression instanceof PsiReferenceExpression)) {
return false;
}
PsiElement target = ((PsiReferenceExpression)expression).resolve();
if (!(target instanceof PsiParameter)) {
return false;
}
if (nullable && NullableNotNullManager.isNullable((PsiParameter)target)) {
return true;
}
if (!nullable && !NullableNotNullManager.isNotNull((PsiParameter)target)) {
return false;
}
}
return true;
}
protected DfaVariableState(final DfaVariableState toClone) {
@@ -42,15 +42,18 @@ import com.intellij.psi.util.*;
import com.intellij.refactoring.psi.PropertyUtils;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import com.intellij.util.Query;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import static com.intellij.util.containers.ContainerUtil.addIfNotNull;
public class NullableStuffInspection extends BaseLocalInspectionTool {
// deprecated fields remain to minimize changes to users inspection profiles (which are often located in version control).
@Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NULLABLE_METHOD_OVERRIDES_NOTNULL = true;
@@ -173,40 +176,13 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
}
}
if (containingClass == null) {
return;
}
final PsiMethod[] constructors = containingClass.getConstructors();
final Query<PsiReference> search = ReferencesSearch.search(field, new LocalSearchScope(constructors), false);
search.forEach(new Processor<PsiReference>() {
@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
if (!(element instanceof PsiReferenceExpression)) {
return true;
}
PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
final PsiAssignmentExpression assignmentExpression = getAssignmentExpressionIfOnAssignmentLefthand(referenceExpression);
final PsiMethod method = PsiTreeUtil.getParentOfType(assignmentExpression, PsiMethod.class);
if (method == null || !method.isConstructor()) {
return true;
}
if (assignmentExpression == null) {
return true;
}
final PsiExpression rhs = assignmentExpression.getRExpression();
if (!(rhs instanceof PsiReferenceExpression)) {
return true;
}
PsiReferenceExpression expression = (PsiReferenceExpression)rhs;
final PsiElement target = expression.resolve();
if (!(target instanceof PsiParameter)) {
return true;
}
final PsiParameter parameter = (PsiParameter)target;
if (!method.equals(parameter.getDeclarationScope())) {
return true;
}
}
for (PsiExpression rhs : findAllConstructorInitializers(field)) {
if (rhs instanceof PsiReferenceExpression) {
PsiElement target = ((PsiReferenceExpression)rhs).resolve();
if (target instanceof PsiParameter) {
PsiParameter parameter = (PsiParameter)target;
if (REPORT_NOT_ANNOTATED_GETTER && !AnnotationUtil.isAnnotated(parameter, manager.getAllAnnotations()) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) {
final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier();
assert nameIdentifier2 != null : parameter;
@@ -214,7 +190,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
.message("inspection.nullable.problems.annotated.field.constructor.parameter.not.annotated",
StringUtil.getShortName(anno)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
return true;
continue;
}
if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false)) {
final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier();
@@ -234,9 +210,9 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove)));
}
return true;
}
});
}
}
}
}
@@ -246,18 +222,6 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
LOG.assertTrue(parameter.isPhysical(), setter.getText());
}
public PsiAssignmentExpression getAssignmentExpressionIfOnAssignmentLefthand(PsiExpression expression) {
PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
if (!(parent instanceof PsiAssignmentExpression)) {
return null;
}
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
if (!PsiTreeUtil.isAncestor(assignmentExpression.getLExpression(), expression, false)) {
return null;
}
return assignmentExpression;
}
@Override public void visitParameter(PsiParameter parameter) {
if (!PsiUtil.isLanguageLevel5OrHigher(parameter)) return;
check(parameter, holder, parameter.getType());
@@ -519,4 +483,42 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD = myReportNullsPassedToNonAnnotatedParameter.isSelected();
}
}
public static List<PsiExpression> findAllConstructorInitializers(PsiField field) {
final List<PsiExpression> result = new ArrayList<PsiExpression>();
addIfNotNull(result, field.getInitializer());
PsiClass containingClass = field.getContainingClass();
if (containingClass != null) {
LocalSearchScope scope = new LocalSearchScope(containingClass.getConstructors());
ReferencesSearch.search(field, scope, false).forEach(new Processor<PsiReference>() {
@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
if (element instanceof PsiReferenceExpression) {
final PsiAssignmentExpression assignment = getAssignmentExpressionIfOnAssignmentLhs(element);
final PsiMethod method = PsiTreeUtil.getParentOfType(assignment, PsiMethod.class);
if (method != null && method.isConstructor() && assignment != null) {
addIfNotNull(result, assignment.getRExpression());
}
}
return true;
}
});
}
return result;
}
@Nullable
private static PsiAssignmentExpression getAssignmentExpressionIfOnAssignmentLhs(PsiElement expression) {
PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
if (!(parent instanceof PsiAssignmentExpression)) {
return null;
}
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
if (!PsiTreeUtil.isAncestor(assignmentExpression.getLExpression(), expression, false)) {
return null;
}
return assignmentExpression;
}
}
@@ -25,12 +25,12 @@ 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;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.EditableModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -39,17 +39,15 @@ import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.*;
import java.util.List;
import java.util.Map;
/**
* @author dsl
* @author Konstantin Bulenkov
*/
public class ChangeClassSignatureDialog extends RefactoringDialog {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeClassSignature.ChangeClassSignatureDialog");
private static final Logger LOG = Logger.getInstance(ChangeClassSignatureDialog.class);
private static final int NAME_COLUMN = 0;
private static final int VALUE_COLUMN = 1;
@@ -61,19 +59,53 @@ public class ChangeClassSignatureDialog extends RefactoringDialog {
private final MyTableModel myTableModel;
private JBTable myTable;
static final String REFACTORING_NAME = RefactoringBundle.message("changeClassSignature.refactoring.name");
private boolean myHideDefaultValueColumn;
public ChangeClassSignatureDialog(PsiClass aClass) {
public ChangeClassSignatureDialog(@NotNull PsiClass aClass, boolean hideDefaultValueColumn) {
this(
aClass,
initTypeParameterInfos(aClass.getTypeParameters().length),
initTypeCodeFragment(aClass.getTypeParameters().length),
hideDefaultValueColumn
);
}
@NotNull
private static List<TypeParameterInfo> initTypeParameterInfos(int length) {
final List<TypeParameterInfo> result = new ArrayList<TypeParameterInfo>();
for (int i = 0; i < length; i++) {
result.add(new TypeParameterInfo(i));
}
return result;
}
@NotNull
private static List<PsiTypeCodeFragment> initTypeCodeFragment(int length) {
final List<PsiTypeCodeFragment> result = new ArrayList<PsiTypeCodeFragment>();
for (int i = 0; i < length; i++) {
result.add(null);
}
return result;
}
public ChangeClassSignatureDialog(@NotNull PsiClass aClass,
@NotNull Map<TypeParameterInfo, PsiTypeCodeFragment> parameters,
boolean hideDefaultValueColumn) {
this(aClass, parameters.keySet(), parameters.values(), hideDefaultValueColumn);
}
public ChangeClassSignatureDialog(@NotNull PsiClass aClass,
@NotNull Collection<TypeParameterInfo> typeParameterInfos,
@NotNull Collection<PsiTypeCodeFragment> typeCodeFragments,
boolean hideDefaultValueColumn) {
super(aClass.getProject(), true);
myHideDefaultValueColumn = hideDefaultValueColumn;
setTitle(REFACTORING_NAME);
myClass = aClass;
myProject = myClass.getProject();
myTypeParameterInfos = new ArrayList<TypeParameterInfo>();
myTypeCodeFragments = new ArrayList<PsiTypeCodeFragment>();
myOriginalParameters = myClass.getTypeParameters();
for (int i = 0; i < myOriginalParameters.length; i++) {
myTypeParameterInfos.add(new TypeParameterInfo(i));
myTypeCodeFragments.add(null);
}
myTypeParameterInfos = new ArrayList<TypeParameterInfo>(typeParameterInfos);
myTypeCodeFragments = new ArrayList<PsiTypeCodeFragment>(typeCodeFragments);
myTableModel = new MyTableModel();
init();
}
@@ -115,26 +147,28 @@ public class ChangeClassSignatureDialog extends RefactoringDialog {
myTable.setCellSelectionEnabled(true);
myTable.setFocusCycleRoot(true);
final TableColumn defaultValue = myTable.getColumnModel().getColumn(1);
myTable.removeColumn(defaultValue);
myTable.getModel().addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.INSERT) {
myTable.getModel().removeTableModelListener(this);
final TableColumnAnimator animator = new TableColumnAnimator(myTable);
animator.setStep(20);
animator.addColumn(defaultValue, myTable.getWidth() / 2);
animator.startAndDoWhenDone(new Runnable() {
@Override
public void run() {
myTable.editCellAt(myTable.getRowCount() - 1, 0);
}
});
animator.start();
if (myHideDefaultValueColumn) {
final TableColumn defaultValue = myTable.getColumnModel().getColumn(VALUE_COLUMN);
myTable.removeColumn(defaultValue);
myTable.getModel().addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.INSERT) {
myTable.getModel().removeTableModelListener(this);
final TableColumnAnimator animator = new TableColumnAnimator(myTable);
animator.setStep(20);
animator.addColumn(defaultValue, myTable.getWidth() / 2);
animator.startAndDoWhenDone(new Runnable() {
@Override
public void run() {
myTable.editCellAt(myTable.getRowCount() - 1, 0);
}
});
animator.start();
}
}
}
});
});
}
final JPanel panel = new JPanel(new BorderLayout());
panel.add(SeparatorFactory.createSeparator(RefactoringBundle.message("changeClassSignature.parameters.panel.border.title"), myTable), BorderLayout.NORTH);
@@ -208,12 +242,13 @@ public class ChangeClassSignatureDialog extends RefactoringDialog {
}
public Object getValueAt(int rowIndex, int columnIndex) {
switch(columnIndex) {
switch (columnIndex) {
case NAME_COLUMN:
TypeParameterInfo info = myTypeParameterInfos.get(rowIndex);
if (info.isForExistingParameter()) {
return myOriginalParameters[info.getOldParameterIndex()].getName();
} else {
}
else {
return info.getNewName();
}
case VALUE_COLUMN:
@@ -228,18 +263,21 @@ public class ChangeClassSignatureDialog extends RefactoringDialog {
}
public String getColumnName(int column) {
switch(column) {
case NAME_COLUMN: return RefactoringBundle.message("column.name.name");
case VALUE_COLUMN: return RefactoringBundle.message("changeSignature.default.value.column");
default: LOG.assertTrue(false);
switch (column) {
case NAME_COLUMN:
return RefactoringBundle.message("column.name.name");
case VALUE_COLUMN:
return RefactoringBundle.message("changeSignature.default.value.column");
default:
LOG.assertTrue(false);
}
return null;
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
switch(columnIndex) {
switch (columnIndex) {
case NAME_COLUMN:
myTypeParameterInfos.get(rowIndex).setNewName((String) aValue);
myTypeParameterInfos.get(rowIndex).setNewName((String)aValue);
break;
case VALUE_COLUMN:
break;
@@ -25,17 +25,17 @@ import org.jetbrains.annotations.NonNls;
/**
* @author dsl
*/
class TypeParameterInfo {
public class TypeParameterInfo {
private final int myOldParameterIndex;
private String myNewName;
private CanonicalTypes.Type myDefaultValue;
TypeParameterInfo(int oldIndex) {
public TypeParameterInfo(int oldIndex) {
myOldParameterIndex = oldIndex;
myDefaultValue = null;
}
TypeParameterInfo(String name, PsiType aType) {
public TypeParameterInfo(String name, PsiType aType) {
myOldParameterIndex = -1;
myNewName = name;
if (aType != null) {
@@ -20,6 +20,8 @@ import com.intellij.ide.util.SuperMethodWarningUtil;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
@@ -99,8 +101,12 @@ public class JavaChangeSignatureHandler implements ChangeSignatureHandler {
}
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, aClass)) return;
ChangeClassSignatureDialog dialog = new ChangeClassSignatureDialog(aClass);
ChangeClassSignatureDialog dialog = new ChangeClassSignatureDialog(aClass, true);
//if (!ApplicationManager.getApplication().isUnitTestMode()){
dialog.show();
//}else {
// dialog.showAndGetOk()
//}
}
@Nullable