From c04ba67a6411bee2de0cc2f84a53af539f639d48 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 2 Oct 2014 19:18:13 +0200 Subject: [PATCH] IDEA-130053 (Fix "Annotate overriding methods" may produce @Nullable @NotNull.) --- .../siyeh/IntentionPowerPackBundle.properties | 4 +- .../AnnotateOverriddenMethodsIntention.java | 56 ++++++++++++------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties index 923df3eb28f4..943131e24867 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties +++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties @@ -149,8 +149,8 @@ if.to.assertion.intention.name=Replace 'if' with 'assert' statement expand.to.normal.annotation.intention.family.name=Expand Annotation to Normal Form expand.to.normal.annotation.intention.name=Add 'value=' to annotation attribute annotate.overridden.methods.intention.family.name=Annotate overriding methods and their parameters -annotate.overridden.methods.intention.method.name=Annotate overriding methods as ''@{0}'' -annotate.overridden.methods.intention.parameters.name=Annotate same parameter of overriding methods as ''@{0}'' +annotate.overridden.methods.intention.method.name=Annotate overriding methods as ''{0}'' +annotate.overridden.methods.intention.parameters.name=Annotate same parameter of overriding methods as ''{0}'' split.multi.catch.intention.name=Split multi-catch into separate 'catch' blocks split.multi.catch.intention.family.name=Split Multi-Catch into Separate Catch Blocks replace.arm.with.try.finally.intention.name=Replace 'try-with-resources' with 'try finally' diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/AnnotateOverriddenMethodsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/AnnotateOverriddenMethodsIntention.java index d4007b28415a..657ed408f4ee 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/AnnotateOverriddenMethodsIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/AnnotateOverriddenMethodsIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 Bas Leijdekkers + * Copyright 2011-2014 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,22 +15,24 @@ */ package com.siyeh.ipp.annotation; +import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.ExternalAnnotationsManager; import com.intellij.codeInsight.FileModificationService; +import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.openapi.command.undo.UndoUtil; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.OverridingMethodsSearch; -import com.intellij.psi.util.ClassUtil; -import com.intellij.util.IncorrectOperationException; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ipp.base.MutablyNamedIntention; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.Collections; +import java.util.List; public class AnnotateOverriddenMethodsIntention extends MutablyNamedIntention { @NotNull @@ -42,32 +44,37 @@ public class AnnotateOverriddenMethodsIntention extends MutablyNamedIntention { @Override protected String getTextForElement(PsiElement element) { final PsiAnnotation annotation = (PsiAnnotation)element; - final String qualifiedName = annotation.getQualifiedName(); - if (qualifiedName == null) { - return null; - } - final String annotationName = ClassUtil.extractClassName(qualifiedName); + final String annotationText = annotation.getText(); final PsiElement grandParent = element.getParent().getParent(); if (grandParent instanceof PsiMethod) { - return IntentionPowerPackBundle.message( - "annotate.overridden.methods.intention.method.name", - annotationName); + return IntentionPowerPackBundle.message("annotate.overridden.methods.intention.method.name", annotationText); } else { - return IntentionPowerPackBundle.message( - "annotate.overridden.methods.intention.parameters.name", - annotationName); + return IntentionPowerPackBundle.message("annotate.overridden.methods.intention.parameters.name", annotationText); } } @Override - protected void processIntention(@NotNull PsiElement element) - throws IncorrectOperationException { + protected void processIntention(@NotNull PsiElement element) { final PsiAnnotation annotation = (PsiAnnotation)element; final String annotationName = annotation.getQualifiedName(); if (annotationName == null) { return; } + final Project project = element.getProject(); + final NullableNotNullManager notNullManager = NullableNotNullManager.getInstance(project); + final List notNulls = notNullManager.getNotNulls(); + final List nullables = notNullManager.getNullables(); + final List annotationsToRemove; + if (notNulls.contains(annotationName)) { + annotationsToRemove = nullables; + } + else if (nullables.contains(annotationName)) { + annotationsToRemove = notNulls; + } + else { + annotationsToRemove = Collections.emptyList(); + } final PsiElement parent = annotation.getParent(); final PsiElement grandParent = parent.getParent(); final PsiMethod method; @@ -95,7 +102,6 @@ public class AnnotateOverriddenMethodsIntention extends MutablyNamedIntention { parameterIndex = -1; method = (PsiMethod)grandParent; } - final Project project = element.getProject(); final Collection overridingMethods = OverridingMethodsSearch.search(method, GlobalSearchScope.allScope(project), true).findAll(); @@ -103,14 +109,14 @@ public class AnnotateOverriddenMethodsIntention extends MutablyNamedIntention { annotation.getParameterList().getAttributes(); for (PsiMethod overridingMethod : overridingMethods) { if (parameterIndex == -1) { - annotate(overridingMethod, annotationName, attributes, element); + annotate(overridingMethod, annotationName, attributes, element, annotationsToRemove); } else { final PsiParameterList parameterList = overridingMethod.getParameterList(); final PsiParameter[] parameters = parameterList.getParameters(); final PsiParameter parameter = parameters[parameterIndex]; - annotate(parameter, annotationName, attributes, element); + annotate(parameter, annotationName, attributes, element, annotationsToRemove); } } } @@ -118,7 +124,8 @@ public class AnnotateOverriddenMethodsIntention extends MutablyNamedIntention { private static void annotate(PsiModifierListOwner modifierListOwner, String annotationName, PsiNameValuePair[] attributes, - PsiElement context) { + PsiElement context, + List annotationsToRemove) { final Project project = context.getProject(); final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project); @@ -138,6 +145,9 @@ public class AnnotateOverriddenMethodsIntention extends MutablyNamedIntention { final PsiFile fromFile = context.getContainingFile(); if (annotationAnnotationPlace == ExternalAnnotationsManager.AnnotationPlace.EXTERNAL) { + for (String annotationToRemove : annotationsToRemove) { + annotationsManager.deannotate(modifierListOwner, annotationToRemove); + } annotationsManager.annotateExternally(modifierListOwner, annotationName, fromFile, attributes); } @@ -147,6 +157,12 @@ public class AnnotateOverriddenMethodsIntention extends MutablyNamedIntention { if (!FileModificationService.getInstance().preparePsiElementForWrite(containingFile)) { return; } + for (String annotationToRemove : annotationsToRemove) { + final PsiAnnotation annotation = AnnotationUtil.findAnnotation(modifierListOwner, annotationToRemove); + if (annotation != null) { + annotation.delete(); + } + } final PsiAnnotation inserted = modifierList.addAnnotation(annotationName); for (PsiNameValuePair pair : attributes) {