AddJavadocIntention: fix exception when the intention invoked for package-info or module-info EA-109542

This commit is contained in:
Dmitry Batkovich
2017-10-25 16:29:40 +03:00
parent 75a2b0cd03
commit f49eb6eaad
4 changed files with 74 additions and 52 deletions
@@ -1,45 +1,41 @@
/*
* Copyright 2000-2014 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-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.
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.editorActions.FixDocCommentAction;
import com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.ide.util.PackageUtil;
import com.intellij.lang.java.JavaDocumentationProvider;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class AddJavadocIntention extends BaseElementAtCaretIntentionAction implements LowPriorityAction {
@Override
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
final PsiDocCommentOwner docCommentOwner = (PsiDocCommentOwner)element.getParent();
FixDocCommentAction.generateOrFixComment(docCommentOwner, project, editor);
FixDocCommentAction.generateOrFixComment(element, project, editor);
}
@Override
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
if (!(element instanceof PsiIdentifier)) {
return false;
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull PsiElement element) {
PsiElement targetElement = PsiTreeUtil.skipParentsOfType(element, PsiIdentifier.class, PsiJavaCodeReferenceElement.class, PsiJavaModuleReferenceElement.class);
if (targetElement instanceof PsiJavaDocumentedElement &&
!(targetElement instanceof PsiTypeParameter) &&
!(targetElement instanceof PsiAnonymousClass)) {
return ((PsiJavaDocumentedElement)targetElement).getDocComment() == null;
}
final PsiElement parent = element.getParent();
return parent instanceof PsiDocCommentOwner &&
((PsiDocCommentOwner)parent).getDocComment() == null &&
!(parent instanceof PsiTypeParameter);
if (targetElement instanceof PsiPackageStatement) {
PsiFile file = targetElement.getContainingFile();
return PackageUtil.isPackageInfoFile(file) && JavaDocumentationProvider.getPackageInfoComment(file) == null;
}
else if (PackageUtil.isPackageInfoFile(targetElement)) {
return JavaDocumentationProvider.getPackageInfoComment(targetElement) == null;
}
return false;
}
@NotNull
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2014 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-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.
package com.intellij.ide.util;
import com.intellij.ide.IdeBundle;
@@ -398,4 +384,8 @@ public class PackageUtil {
public static PsiDirectory findOrCreateSubdirectory(@NotNull PsiDirectory directory, @NotNull String directoryName) {
return CreateFileAction.findOrCreateSubdirectory(directory, directoryName);
}
public static boolean isPackageInfoFile(@Nullable PsiElement element) {
return element instanceof PsiJavaFile && PsiPackage.PACKAGE_INFO_FILE.equals(((PsiJavaFile)element).getName());
}
}
@@ -1,6 +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-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.
package com.intellij.lang.java;
import com.intellij.codeInsight.CodeInsightBundle;
@@ -12,6 +10,7 @@ import com.intellij.codeInsight.javadoc.JavaDocExternalFilter;
import com.intellij.codeInsight.javadoc.JavaDocInfoGenerator;
import com.intellij.codeInsight.javadoc.JavaDocInfoGeneratorFactory;
import com.intellij.codeInsight.javadoc.JavaDocUtil;
import com.intellij.ide.util.PackageUtil;
import com.intellij.lang.CodeDocumentationAwareCommenter;
import com.intellij.lang.LangBundle;
import com.intellij.lang.LanguageCommenters;
@@ -392,18 +391,18 @@ public class JavaDocumentationProvider extends DocumentationProviderEx implement
@Nullable
@Override
public Pair<PsiElement, PsiComment> parseContext(@NotNull PsiElement startPoint) {
PsiElement docCommentOwner = PsiTreeUtil.findFirstParent(startPoint, e -> {
if (e instanceof PsiDocCommentOwner && !(e instanceof PsiTypeParameter) && !(e instanceof PsiAnonymousClass)) {
return true;
PsiElement current = startPoint;
while (current != null) {
if (current instanceof PsiJavaDocumentedElement && !(current instanceof PsiTypeParameter) && !(current instanceof PsiAnonymousClass)) {
PsiDocComment comment = ((PsiJavaDocumentedElement)current).getDocComment();
return Pair.create(current instanceof PsiField ? ((PsiField)current).getModifierList() : current, comment);
}
return false;
});
if (docCommentOwner == null) return null;
PsiDocComment comment = ((PsiDocCommentOwner)docCommentOwner).getDocComment();
if (docCommentOwner instanceof PsiField) {
docCommentOwner = ((PsiField)docCommentOwner).getModifierList();
else if (PackageUtil.isPackageInfoFile(current)) {
return Pair.create(current, getPackageInfoComment(current));
}
current = current.getParent();
}
return Pair.create(docCommentOwner, comment);
return null;
}
@Override
@@ -730,6 +729,11 @@ public class JavaDocumentationProvider extends DocumentationProviderEx implement
return signature;
}
@Nullable
public static PsiDocComment getPackageInfoComment(@NotNull PsiElement packageInfoFile) {
return PsiTreeUtil.getChildOfType(packageInfoFile, PsiDocComment.class);
}
@Nullable
public static List<String> findUrlForClass(@NotNull PsiClass aClass) {
String qName = aClass.getQualifiedName();
@@ -0,0 +1,32 @@
// 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.
package com.intellij.java.codeInsight.intention;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
public class AddJavadocToModuleAndPackageTest extends LightCodeInsightFixtureTestCase {
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_9;
}
public void testPackageInfo() {
myFixture.configureByText("package-info.java", "package org.some.awe<caret>some;");
myFixture.launchAction(myFixture.findSingleIntention("Add Javadoc"));
myFixture.checkResult("/**\n" +
" * \n" +
" */\n" +
"package org.some.awesome;");
}
public void testModuleInfo() {
myFixture.configureByText("module-info.java", "module org.some.awe<caret>some{}");
myFixture.launchAction(myFixture.findSingleIntention("Add Javadoc"));
myFixture.checkResult("/**\n" +
" * \n" +
" */\n" +
"module org.some.awesome{}");
}
}