From cc8d990786d180b3f65a7c03ad66c204572ee7c5 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Tue, 24 Oct 2017 10:37:09 +0300 Subject: [PATCH] redundant throws fix should remove javadoc tag too (IDEA-185105) --- .../daemon/impl/quickfix/MethodThrowsFix.java | 31 +++++++++++++---- .../codeInsight/javadoc/JavaDocUtil.java | 34 +++++++++++-------- .../source/javadoc/ClassReferenceTagInfo.java | 17 +--------- .../impl/source/javadoc/ExceptionTagInfo.java | 6 ++-- .../quickFix/methodThrows/afterJavadoc.java | 11 ++++++ .../quickFix/methodThrows/beforeJavadoc.java | 12 +++++++ 6 files changed, 72 insertions(+), 39 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodThrows/afterJavadoc.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodThrows/beforeJavadoc.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodThrowsFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodThrowsFix.java index f22b48729041..40a2d203175e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodThrowsFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodThrowsFix.java @@ -2,6 +2,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.javadoc.JavaDocUtil; import com.intellij.codeInspection.LocalQuickFixOnPsiElement; import com.intellij.openapi.command.undo.UndoUtil; import com.intellij.openapi.diagnostic.Logger; @@ -9,11 +10,14 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; + public class MethodThrowsFix extends LocalQuickFixOnPsiElement { private static final Logger LOG = Logger.getInstance(MethodThrowsFix.class); @@ -69,12 +73,27 @@ public class MethodThrowsFix extends LocalQuickFixOnPsiElement { } } } - if (myAddThrow && !alreadyThrows) { - final PsiElementFactory factory = JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory(); - final PsiClassType type = (PsiClassType)factory.createTypeFromText(myThrowsCanonicalText, myMethod); - PsiJavaCodeReferenceElement ref = factory.createReferenceElementByType(type); - ref = (PsiJavaCodeReferenceElement)JavaCodeStyleManager.getInstance(project).shortenClassReferences(ref); - myMethod.getThrowsList().add(ref); + if (myAddThrow) { + if (!alreadyThrows) { + final PsiElementFactory factory = JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory(); + final PsiClassType type = (PsiClassType)factory.createTypeFromText(myThrowsCanonicalText, myMethod); + PsiJavaCodeReferenceElement ref = factory.createReferenceElementByType(type); + ref = (PsiJavaCodeReferenceElement)JavaCodeStyleManager.getInstance(project).shortenClassReferences(ref); + myMethod.getThrowsList().add(ref); + } + } else { + PsiDocComment comment = myMethod.getDocComment(); + if (comment != null) { + Arrays + .stream(comment.getTags()) + .filter(tag -> "throws".equals(tag.getName())) + .filter(tag -> { + PsiClass tagValueClass = JavaDocUtil.resolveClassInTagValue(tag.getValueElement()); + return tagValueClass != null && myThrowsCanonicalText.equals(tagValueClass.getQualifiedName()); + }) + .forEach(tag -> tag.delete()); + } + } UndoUtil.markPsiFileForUndo(file); } diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java index ec8cf784ad08..ab51e18a477b 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInsight.javadoc; import com.intellij.openapi.diagnostic.Logger; @@ -21,6 +7,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.IncorrectOperationException; @@ -39,6 +26,23 @@ public class JavaDocUtil { private JavaDocUtil() { } + @Nullable + public static PsiClass resolveClassInTagValue(@Nullable PsiDocTagValue value) { + if (value == null) return null; + PsiElement refHolder = value.getFirstChild(); + if (refHolder != null) { + PsiElement refElement = refHolder.getFirstChild(); + if (refElement instanceof PsiJavaCodeReferenceElement) { + PsiElement target = ((PsiJavaCodeReferenceElement)refElement).resolve(); + if (target instanceof PsiClass) { + return (PsiClass)target; + } + } + } + + return null; + } + /** * Extracts a reference to a source element from the beginning of the text. * diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ClassReferenceTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ClassReferenceTagInfo.java index a344179f4c3d..5971e732d0cf 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ClassReferenceTagInfo.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ClassReferenceTagInfo.java @@ -1,4 +1,4 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.impl.source.javadoc; import com.intellij.codeInsight.daemon.JavaErrorMessages; @@ -45,19 +45,4 @@ abstract class ClassReferenceTagInfo implements JavadocTagInfo { public PsiReference getReference(PsiDocTagValue value) { return null; } - - protected static PsiClass resolveClass(PsiDocTagValue value) { - PsiElement refHolder = value.getFirstChild(); - if (refHolder != null) { - PsiElement refElement = refHolder.getFirstChild(); - if (refElement instanceof PsiJavaCodeReferenceElement) { - PsiElement target = ((PsiJavaCodeReferenceElement)refElement).resolve(); - if (target instanceof PsiClass) { - return (PsiClass)target; - } - } - } - - return null; - } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ExceptionTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ExceptionTagInfo.java index b600e7afea82..09e6b3825b4d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ExceptionTagInfo.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ExceptionTagInfo.java @@ -1,4 +1,4 @@ -// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.impl.source.javadoc; import com.intellij.codeInsight.daemon.JavaErrorMessages; @@ -6,6 +6,8 @@ import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.codeInsight.javadoc.JavaDocUtil.resolveClassInTagValue; + /** * @author mike */ @@ -24,7 +26,7 @@ class ExceptionTagInfo extends ClassReferenceTagInfo { String result = super.checkTagValue(value); if (result != null) return result; - PsiClass exceptionClass = resolveClass(value); + PsiClass exceptionClass = resolveClassInTagValue(value); if (exceptionClass == null) return null; PsiClass throwable = JavaPsiFacade.getInstance(value.getProject()).findClass(CommonClassNames.JAVA_LANG_THROWABLE, value.getResolveScope()); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodThrows/afterJavadoc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodThrows/afterJavadoc.java new file mode 100644 index 000000000000..59939b180189 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodThrows/afterJavadoc.java @@ -0,0 +1,11 @@ +// "Remove 'IOException' from 'foo' throws list" "true" +import java.io.*; + +class A { + /** + * some description + */ + private void foo() { + } +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodThrows/beforeJavadoc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodThrows/beforeJavadoc.java new file mode 100644 index 000000000000..945acf9524a5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodThrows/beforeJavadoc.java @@ -0,0 +1,12 @@ +// "Remove 'IOException' from 'foo' throws list" "true" +import java.io.*; + +class A { + /** + * some description + * @throws IOException + */ + private void foo() throws IOException { + } +} +