summaryrefslogtreecommitdiff
path: root/java/java-impl/src/com/intellij
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2013-04-03 16:27:26 -0700
committerTor Norbye <tnorbye@google.com>2013-04-03 16:27:26 -0700
commitd1a59a0799588a226d255d9b45c4825b19651554 (patch)
treec9759b94ddad742db08b6662f52a62e0401491c1 /java/java-impl/src/com/intellij
parent2bd2b7c2623d4266384e890271869efc044aabff (diff)
downloadidea-d1a59a0799588a226d255d9b45c4825b19651554.tar.gz
Snapshot dc7fe9a777db5bc87a5b1ad4bfe40a547fc7d49a from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: Iae1c655b8958fc7603a78c675e4a4b942a1fccd4
Diffstat (limited to 'java/java-impl/src/com/intellij')
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java135
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java1
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java1
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java4
-rw-r--r--java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldCentralPanel.java32
-rw-r--r--java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialogPanel.java15
-rw-r--r--java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldPopupPanel.java15
-rw-r--r--java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java18
8 files changed, 198 insertions, 23 deletions
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
index 98b582f73545..69398342cff4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
@@ -30,6 +30,7 @@ import com.intellij.patterns.ElementPattern;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.PsiClassReferenceType;
+import com.intellij.psi.impl.source.PsiImmediateClassType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -38,6 +39,7 @@ import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -172,10 +174,38 @@ public class AnnotationsHighlightUtil {
PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
if (nameRef == null) continue;
PsiElement aClass = nameRef.resolve();
- if (resolved.equals(aClass)) {
+ if (!resolved.equals(aClass)) continue;
+
+ if (!PsiUtil.isLanguageLevel8OrHigher(annotationToCheck)) {
String description = JavaErrorMessages.message("annotation.duplicate.annotation");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create();
}
+
+ PsiClass annotationType = (PsiClass)resolved;
+ PsiAnnotation metaAnno = PsiImplUtil.findAnnotation(annotationType.getModifierList(), CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE);
+ if (metaAnno == null) {
+ String explanation = JavaErrorMessages.message("annotation.non.repeatable", annotationType.getQualifiedName());
+ String description = JavaErrorMessages.message("annotation.duplicate.explained", explanation);
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create();
+ }
+
+ String explanation = doCheckRepeatableAnnotation(metaAnno);
+ if (explanation != null) {
+ String description = JavaErrorMessages.message("annotation.duplicate.explained", explanation);
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create();
+ }
+
+ PsiClass collector = getRepeatableCollector(metaAnno);
+ if (collector != null) {
+ String collectorName = collector.getQualifiedName();
+ if (collectorName != null) {
+ PsiAnnotation collectorAnno = owner.findAnnotation(collectorName);
+ if (collectorAnno != null) {
+ String description = JavaErrorMessages.message("annotation.collector.wrong.place", collectorName);
+ return annotationError(collectorAnno, description);
+ }
+ }
+ }
}
return null;
@@ -458,9 +488,11 @@ public class AnnotationsHighlightUtil {
public static HighlightInfo checkTargetAnnotationDuplicates(PsiAnnotation annotation) {
PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
if (nameRef == null) return null;
+
PsiElement resolved = nameRef.resolve();
- if (!(resolved instanceof PsiClass) ||
- !CommonClassNames.TARGET_ANNOTATION_FQ_NAME.equals(((PsiClass) resolved).getQualifiedName())) return null;
+ if (!(resolved instanceof PsiClass) || !CommonClassNames.JAVA_LANG_ANNOTATION_TARGET.equals(((PsiClass)resolved).getQualifiedName())) {
+ return null;
+ }
PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
if (attributes.length < 1) return null;
@@ -483,6 +515,7 @@ public class AnnotationsHighlightUtil {
return null;
}
+ @Nullable
public static HighlightInfo checkFunctionalInterface(PsiAnnotation annotation) {
final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation);
if (errorMessage != null) {
@@ -491,6 +524,90 @@ public class AnnotationsHighlightUtil {
return null;
}
+ @Nullable
+ public static HighlightInfo checkRepeatableAnnotation(PsiAnnotation annotation) {
+ String qualifiedName = annotation.getQualifiedName();
+ if (!CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE.equals(qualifiedName)) return null;
+
+ String description = doCheckRepeatableAnnotation(annotation);
+ if (description != null) {
+ PsiAnnotationMemberValue collectorRef = PsiImplUtil.findAttributeValue(annotation, null);
+ if (collectorRef != null) {
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(collectorRef).descriptionAndTooltip(description).create();
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ private static String doCheckRepeatableAnnotation(PsiAnnotation annotation) {
+ PsiAnnotationOwner owner = annotation.getOwner();
+ if (!(owner instanceof PsiModifierList)) return null;
+ PsiElement target = ((PsiModifierList)owner).getParent();
+ if (!(target instanceof PsiClass) || !((PsiClass)target).isAnnotationType()) return null;
+ PsiClass collector = getRepeatableCollector(annotation);
+ if (collector == null) return null;
+
+ PsiMethod[] methods = collector.findMethodsByName("value", false);
+ if (methods.length == 0) {
+ return JavaErrorMessages.message("annotation.container.no.value", collector.getQualifiedName());
+ }
+
+ if (methods.length == 1) {
+ PsiType expected = new PsiImmediateClassType((PsiClass)target, PsiSubstitutor.EMPTY).createArrayType();
+ if (!expected.equals(methods[0].getReturnType())) {
+ return JavaErrorMessages.message("annotation.container.bad.type", collector.getQualifiedName(), HighlightUtil.formatType(expected));
+ }
+ }
+
+ RetentionPolicy targetPolicy = getRetentionPolicy((PsiClass)target);
+ if (targetPolicy != null) {
+ RetentionPolicy collectorPolicy = getRetentionPolicy(collector);
+ if (collectorPolicy != null && targetPolicy.compareTo(collectorPolicy) > 0) {
+ return JavaErrorMessages.message("annotation.container.low.retention", collector.getQualifiedName(), collectorPolicy);
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ private static PsiClass getRepeatableCollector(PsiAnnotation annotation) {
+ PsiAnnotationMemberValue collectorRef = PsiImplUtil.findAttributeValue(annotation, null);
+ if (!(collectorRef instanceof PsiClassObjectAccessExpression)) return null;
+ PsiType collectorType = ((PsiClassObjectAccessExpression)collectorRef).getOperand().getType();
+ if (!(collectorType instanceof PsiClassType)) return null;
+ PsiClass collector = ((PsiClassType)collectorType).resolve();
+ if (collector == null || !collector.isAnnotationType()) return null;
+ return collector;
+ }
+
+ @Nullable
+ private static RetentionPolicy getRetentionPolicy(PsiClass annotation) {
+ PsiModifierList modifierList = annotation.getModifierList();
+ if (modifierList != null) {
+ PsiAnnotation retentionAnno = modifierList.findAnnotation(CommonClassNames.JAVA_LANG_ANNOTATION_RETENTION);
+ if (retentionAnno == null) return RetentionPolicy.CLASS;
+
+ PsiAnnotationMemberValue policyRef = PsiImplUtil.findAttributeValue(retentionAnno, null);
+ if (policyRef instanceof PsiReference) {
+ PsiElement field = ((PsiReference)policyRef).resolve();
+ if (field instanceof PsiEnumConstant) {
+ String name = ((PsiEnumConstant)field).getName();
+ try {
+ return RetentionPolicy.valueOf(name);
+ }
+ catch (Exception e) {
+ LOG.warn("Unknown policy: " + name);
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
public static class AnnotationReturnTypeVisitor extends PsiTypeVisitor<Boolean> {
public static final AnnotationReturnTypeVisitor INSTANCE = new AnnotationReturnTypeVisitor();
@Override
@@ -514,15 +631,15 @@ public class AnnotationsHighlightUtil {
public Boolean visitClassType(PsiClassType classType) {
if (classType.getParameters().length > 0) {
PsiClassType rawType = classType.rawType();
- if (rawType.equalsToText("java.lang.Class")) {
- return Boolean.TRUE;
- }
- return Boolean.FALSE;
+ return rawType.equalsToText(CommonClassNames.JAVA_LANG_CLASS);
}
+
PsiClass aClass = classType.resolve();
- if (aClass != null && (aClass.isAnnotationType() || aClass.isEnum())) return Boolean.TRUE;
+ if (aClass != null && (aClass.isAnnotationType() || aClass.isEnum())) {
+ return Boolean.TRUE;
+ }
- return classType.equalsToText("java.lang.Class") || classType.equalsToText("java.lang.String") ? Boolean.TRUE : Boolean.FALSE;
+ return classType.equalsToText(CommonClassNames.JAVA_LANG_CLASS) || classType.equalsToText(CommonClassNames.JAVA_LANG_STRING);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
index 3b6ef960f407..9e6f8a85cedb 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
@@ -183,6 +183,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicateAnnotations(annotation));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkForeignInnerClassesUsed(annotation));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkFunctionalInterface(annotation));
+ if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkRepeatableAnnotation(annotation));
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java
index dfc477ac173d..79c7dd9ecca0 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java
@@ -311,7 +311,6 @@ public class SimplifyBooleanExpressionFix implements IntentionAction {
}
catch (IncorrectOperationException e) {
resultExpression = null;
- LOG.error("lExpr: " + lExpr.getText() + "; op: " + javaToken.getText() + "; rExpr: " + operand.getText() + "; top: " + expression.getText());
}
}
else {
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
index 98d8894c7034..f12fe42d4824 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -477,7 +477,7 @@ public class GenerateMembersUtil {
else {
JVMElementFactory factory = JVMElementFactories.requireFactory(targetParam.getLanguage(), targetParam.getProject());
for (PsiAnnotation annotation : sourceModifierList.getAnnotations()) {
- targetModifierList.add(factory.createAnnotationFromText(annotation.getText(), targetParam));
+ targetModifierList.add(factory.createAnnotationFromText(annotation.getText(), sourceParam));
}
for (@PsiModifier.ModifierConstant String m : PsiModifier.MODIFIERS) {
targetModifierList.setModifierProperty(m, sourceParam.hasModifierProperty(m));
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldCentralPanel.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldCentralPanel.java
index 68d5e99cc536..da5be799dace 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldCentralPanel.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldCentralPanel.java
@@ -15,15 +15,19 @@
*/
package com.intellij.refactoring.introduceField;
+import com.intellij.codeInsight.TestFrameworks;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.ui.TypeSelectorManager;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.ui.StateRestoringCheckBox;
+import com.intellij.util.Processor;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
@@ -93,7 +97,7 @@ public abstract class IntroduceFieldCentralPanel {
refElement instanceof PsiParameter ||
(refElement instanceof PsiField && !((PsiField)refElement).hasInitializer())) &&
!PsiTreeUtil.isAncestor(initializer, refElement, true)) {
- return updateInitializationPlaceModel();
+ return updateInitializationPlaceModel(initializedInSetUp(refElement));
}
}
}
@@ -104,6 +108,28 @@ public abstract class IntroduceFieldCentralPanel {
return true;
}
+ private boolean initializedInSetUp(PsiElement refElement) {
+ if (refElement instanceof PsiField && hasSetUpChoice()) {
+ final PsiMethod setUpMethod = TestFrameworks.getInstance().findSetUpMethod(((PsiField)refElement).getContainingClass());
+ if (setUpMethod != null) {
+ final Processor<PsiReference> initializerSearcher = new Processor<PsiReference>() {
+ @Override
+ public boolean process(PsiReference reference) {
+ final PsiElement referenceElement = reference.getElement();
+ if (referenceElement instanceof PsiExpression) {
+ return !PsiUtil.isAccessedForWriting((PsiExpression)referenceElement);
+ }
+ return true;
+ }
+ };
+ if (!ReferencesSearch.search(refElement, new LocalSearchScope(setUpMethod)).forEach(initializerSearcher)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public abstract BaseExpressionToFieldHandler.InitializationPlace getInitializerPlace();
protected abstract void initializeInitializerPlace(PsiExpression initializerExpression,
BaseExpressionToFieldHandler.InitializationPlace ourLastInitializerPlace);
@@ -279,5 +305,7 @@ public abstract class IntroduceFieldCentralPanel {
}
}
- protected abstract boolean updateInitializationPlaceModel();
+ protected abstract boolean updateInitializationPlaceModel(boolean initializedInsetup);
+
+ protected abstract boolean hasSetUpChoice();
}
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialogPanel.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialogPanel.java
index a184983897ba..ad5ccbc6fa18 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialogPanel.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialogPanel.java
@@ -195,14 +195,25 @@ public class IntroduceFieldDialogPanel extends IntroduceFieldCentralPanel {
}
@Override
- protected boolean updateInitializationPlaceModel() {
+ protected boolean updateInitializationPlaceModel(boolean initializedInSetup) {
myRbInFieldDeclaration.setEnabled(false);
myRbInConstructor.setEnabled(false);
- if (myRbInSetUp != null) myRbInSetUp.setEnabled(false);
enableFinal(false);
+ if (myRbInSetUp != null){
+ if (!initializedInSetup) {
+ myRbInSetUp.setEnabled(false);
+ } else {
+ return true;
+ }
+ }
return false;
}
+ @Override
+ protected boolean hasSetUpChoice() {
+ return myRbInSetUp != null;
+ }
+
public void setInitializeInFieldDeclaration() {
myRbInFieldDeclaration.setSelected(true);
}
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldPopupPanel.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldPopupPanel.java
index e0e26cbaf4dd..0583a16b5bdb 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldPopupPanel.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldPopupPanel.java
@@ -66,7 +66,7 @@ public class IntroduceFieldPopupPanel extends IntroduceFieldCentralPanel {
}
final PsiMethod setUpMethod = TestFrameworks.getInstance().findSetUpMethod(myParentClass);
- final boolean setupEnabled = myInitialisersPlaceModel.getIndexOf(BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD) > -1;
+ final boolean setupEnabled = hasSetUpChoice();
if (ourLastInitializerPlace == BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD &&
setupEnabled && (myInitializerExpression != null && PsiTreeUtil.isAncestor(setUpMethod, myInitializerExpression, false) ||
TestFrameworks.getInstance().isTestClass(myParentClass))) {
@@ -187,13 +187,22 @@ public class IntroduceFieldPopupPanel extends IntroduceFieldCentralPanel {
}
@Override
- protected boolean updateInitializationPlaceModel() {
+ protected boolean updateInitializationPlaceModel(boolean initializedInSetup) {
myInitialisersPlaceModel.removeElement(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION);
myInitialisersPlaceModel.removeElement(BaseExpressionToFieldHandler.InitializationPlace.IN_CONSTRUCTOR);
- myInitialisersPlaceModel.removeElement(BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD);
+ if (!initializedInSetup) {
+ myInitialisersPlaceModel.removeElement(BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD);
+ } else {
+ return true;
+ }
return false;
}
+ @Override
+ protected boolean hasSetUpChoice() {
+ return myInitialisersPlaceModel.getIndexOf(BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD) > -1;
+ }
+
public void setInitializeInFieldDeclaration() {
LOG.assertTrue(myInitializerCombo != null);
myInitializerCombo.setSelectedItem(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION);
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
index 3423cca5bd30..b2aa15916b26 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
@@ -197,12 +197,22 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
PsiExpression expression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class);
while (expression != null) {
if (!expressions.contains(expression) && !(expression instanceof PsiParenthesizedExpression) && !(expression instanceof PsiSuperExpression) && expression.getType() != PsiType.VOID) {
- if (expression instanceof PsiMethodReferenceExpression ||
- !(expression instanceof PsiReferenceExpression &&
- (expression.getParent() instanceof PsiMethodCallExpression || ((PsiReferenceExpression)expression).resolve() instanceof PsiClass)) &&
- !(expression instanceof PsiAssignmentExpression)) {
+ if (expression instanceof PsiMethodReferenceExpression) {
expressions.add(expression);
}
+ else if (!(expression instanceof PsiAssignmentExpression)) {
+ if (!(expression instanceof PsiReferenceExpression)) {
+ expressions.add(expression);
+ }
+ else {
+ if (!(expression.getParent() instanceof PsiMethodCallExpression)) {
+ final PsiElement resolve = ((PsiReferenceExpression)expression).resolve();
+ if (!(resolve instanceof PsiClass) && !(resolve instanceof PsiPackage)) {
+ expressions.add(expression);
+ }
+ }
+ }
+ }
}
expression = PsiTreeUtil.getParentOfType(expression, PsiExpression.class);
}