diff options
author | Tor Norbye <tnorbye@google.com> | 2013-05-31 07:45:51 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2013-05-31 07:45:51 -0700 |
commit | ec3fb1e06285c0467a7a20360ca80453bc7635d4 (patch) | |
tree | 2402cdec34611f34b8385ff45387d6734bf6f994 /plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc | |
parent | a6eac331b3d9f0d4168b12356ea256c83f4e9c05 (diff) | |
download | idea-ec3fb1e06285c0467a7a20360ca80453bc7635d4.tar.gz |
Snapshot 568f05589922685b8c8f9a2f2f465043b8128542 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: I47fe8cb5d8a3c9876cd4c313dca1a8cc531288ec
Diffstat (limited to 'plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc')
3 files changed, 557 insertions, 0 deletions
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java new file mode 100644 index 000000000000..261382652a47 --- /dev/null +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java @@ -0,0 +1,184 @@ +/* + * Copyright 2011-2012 Bas Leijdekkers + * + * 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.siyeh.ig.javadoc; + +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.JavaDocTokenType; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementFactory; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.javadoc.PsiDocToken; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.InspectionGadgetsFix; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class HtmlTagCanBeJavadocTagInspection extends BaseInspection { + + @Nls + @NotNull + @Override + public String getDisplayName() { + return InspectionGadgetsBundle.message("html.tag.can.be.javadoc.tag.display.name"); + } + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + return InspectionGadgetsBundle.message("html.tag.can.be.javadoc.tag.problem.descriptor"); + } + + @Override + protected InspectionGadgetsFix buildFix(Object... infos) { + final int offset = ((Integer)infos[0]).intValue(); + return new HtmlTagCanBeJavaDocTagFix(offset); + } + + private static class HtmlTagCanBeJavaDocTagFix extends InspectionGadgetsFix { + + private final int startIndex; + + public HtmlTagCanBeJavaDocTagFix(int startIndex) { + this.startIndex = startIndex; + } + + @Override + @NotNull + public String getName() { + return InspectionGadgetsBundle.message( + "html.tag.can.be.javadoc.tag.quickfix"); + } + + @Override + protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { + final PsiElement element = descriptor.getPsiElement(); + final PsiDocComment comment = PsiTreeUtil.getParentOfType(element, PsiDocComment.class); + if (comment == null) { + return; + } + @NonNls final StringBuilder newCommentText = new StringBuilder(); + buildNewCommentText(comment, element, false, newCommentText); + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + final PsiDocComment newComment = factory.createDocCommentFromText(newCommentText.toString()); + comment.replace(newComment); + } + + private boolean buildNewCommentText(PsiElement element, PsiElement elementToReplace, boolean missingEndTag, + @NonNls StringBuilder newCommentText) { + final PsiElement[] children = element.getChildren(); + if (children.length != 0) { + for (PsiElement child : children) { + missingEndTag = buildNewCommentText(child, elementToReplace, missingEndTag, newCommentText); + } + return missingEndTag; + } + @NonNls final String text = element.getText(); + if (element != elementToReplace) { + if (missingEndTag) { + final int endIndex = text.indexOf("</code>"); + if (endIndex >= 0) { + final String codeText = text.substring(0, endIndex); + newCommentText.append(codeText); + newCommentText.append('}'); + newCommentText.append(text.substring(endIndex + 7)); + return false; + } + } + newCommentText.append(text); + } + else { + newCommentText.append(text.substring(0, startIndex)); + newCommentText.append("{@code "); + final int endIndex = text.indexOf("</code>", startIndex); + if (endIndex >= 0) { + final String codeText = text.substring(startIndex + 6, endIndex); + newCommentText.append(codeText); + //StringUtil.replace(codeText, "}", "}")); + newCommentText.append('}'); + newCommentText.append(text.substring(endIndex + 7)); + } + else { + final String codeText = text.substring(startIndex + 6); + newCommentText.append(codeText); + //StringUtil.replace(codeText, "}", "}")); + return true; + } + } + return missingEndTag; + } + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new HtmlTagCanBeJavaDocTagVisitor(); + } + + private static class HtmlTagCanBeJavaDocTagVisitor extends BaseInspectionVisitor { + + @Override + public void visitDocToken(PsiDocToken token) { + super.visitDocToken(token); + if (!PsiUtil.isLanguageLevel5OrHigher(token)) { + return; + } + final IElementType tokenType = token.getTokenType(); + if (!JavaDocTokenType.DOC_COMMENT_DATA.equals(tokenType)) { + return; + } + @NonNls final String text = token.getText(); + int startIndex = 0; + while (true) { + startIndex = text.indexOf("<code>", startIndex); + if (startIndex < 0) { + return; + } + if (hasMatchingCloseTag(token, startIndex + 6)) { + registerErrorAtOffset(token, startIndex, 6, Integer.valueOf(startIndex)); + } + startIndex++; + } + } + + private static boolean hasMatchingCloseTag(PsiElement element, int offset) { + final String text = element.getText(); + final int endOffset1 = text.indexOf("</code>", offset); + if (endOffset1 >= 0) { + final int startOffset1 = text.indexOf("<code>", offset); + return startOffset1 < 0 || startOffset1 > endOffset1; + } + PsiElement sibling = element.getNextSibling(); + while (sibling != null) { + final String text1 = sibling.getText(); + final int endOffset = text1.indexOf("</code>"); + if (endOffset >= 0) { + final int startOffset = text1.indexOf("<code>"); + return startOffset < 0 || startOffset > endOffset; + } + sibling = sibling.getNextSibling(); + } + return false; + } + } +} diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryInheritDocInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryInheritDocInspection.java new file mode 100644 index 000000000000..c1f05d78f82a --- /dev/null +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryInheritDocInspection.java @@ -0,0 +1,120 @@ +/* + * Copyright 2009-2011 Bas Leijdekkers + * + * 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.siyeh.ig.javadoc; + +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.JavaDocTokenType; +import com.intellij.psi.PsiElement; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.javadoc.PsiDocTag; +import com.intellij.psi.javadoc.PsiDocToken; +import com.intellij.psi.javadoc.PsiInlineDocTag; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.InspectionGadgetsFix; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class UnnecessaryInheritDocInspection extends BaseInspection { + + @Nls + @NotNull + @Override + public String getDisplayName() { + return InspectionGadgetsBundle.message( + "unnecessary.inherit.doc.display.name"); + } + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + return InspectionGadgetsBundle.message( + "unnecessary.inherit.doc.problem.descriptor"); + } + + @Override + protected InspectionGadgetsFix buildFix(Object... infos) { + return new UnnecessaryInheritDocFix(); + } + + private static class UnnecessaryInheritDocFix extends InspectionGadgetsFix { + + @Override + @NotNull + public String getName() { + return InspectionGadgetsBundle.message( + "unnecessary.inherit.doc.quickfix"); + } + + @Override + protected void doFix(Project project, ProblemDescriptor descriptor) + throws IncorrectOperationException { + final PsiElement element = descriptor.getPsiElement(); + if (!(element instanceof PsiDocTag)) { + return; + } + final PsiDocTag docTag = (PsiDocTag)element; + final PsiDocComment docComment = docTag.getContainingComment(); + docComment.delete(); + } + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new UnnecessaryInheritDocVisitor(); + } + + private static class UnnecessaryInheritDocVisitor + extends BaseInspectionVisitor { + + @Override + public void visitDocTag(PsiDocTag tag) { + if (!(tag instanceof PsiInlineDocTag)) { + return; + } + @NonNls final String name = tag.getName(); + if (!"inheritDoc".equals(name)) { + return; + } + final PsiDocComment docComment = tag.getContainingComment(); + if (docComment == null) { + return; + } + final PsiDocToken[] docTokens = PsiTreeUtil.getChildrenOfType( + docComment, PsiDocToken.class); + if (docTokens == null) { + return; + } + for (PsiDocToken docToken : docTokens) { + final IElementType tokenType = docToken.getTokenType(); + if (!JavaDocTokenType.DOC_COMMENT_DATA.equals(tokenType)) { + continue; + } + if (!StringUtil.isEmptyOrSpaces(docToken.getText())) { + return; + } + } + registerError(tag); + } + } +} diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryJavaDocLinkInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryJavaDocLinkInspection.java new file mode 100644 index 000000000000..63b1d756841b --- /dev/null +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryJavaDocLinkInspection.java @@ -0,0 +1,253 @@ +/* + * Copyright 2009-2011 Bas Leijdekkers + * + * 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.siyeh.ig.javadoc; + +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.javadoc.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.MethodSignature; +import com.intellij.psi.util.MethodSignatureUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.InspectionGadgetsFix; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +public class UnnecessaryJavaDocLinkInspection extends BaseInspection { + + private static final int THIS_METHOD = 1; + private static final int THIS_CLASS = 2; + private static final int SUPER_METHOD = 3; + + @SuppressWarnings({"PublicField"}) + public boolean ignoreInlineLinkToSuper = false; + + @Nls + @NotNull + @Override + public String getDisplayName() { + return InspectionGadgetsBundle.message( + "unnecessary.javadoc.link.display.name"); + } + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + final int n = ((Integer)infos[1]).intValue(); + if (n == THIS_METHOD) { + return InspectionGadgetsBundle.message( + "unnecessary.javadoc.link.this.method.problem.descriptor"); + } + if (n == THIS_CLASS) { + return InspectionGadgetsBundle.message( + "unnecessary.javadoc.link.this.class.problem.descriptor"); + } + return InspectionGadgetsBundle.message( + "unnecessary.javadoc.link.super.method.problem.descriptor"); + } + + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel( + InspectionGadgetsBundle.message( + "unnecessary.javadoc.link.option"), + this, "ignoreInlineLinkToSuper"); + } + + @Override + protected InspectionGadgetsFix buildFix(Object... infos) { + return new UnnecessaryJavaDocLinkFix((String)infos[0]); + } + + private static class UnnecessaryJavaDocLinkFix + extends InspectionGadgetsFix { + + private final String tagName; + + public UnnecessaryJavaDocLinkFix(String tagName) { + this.tagName = tagName; + } + + @Override + @NotNull + public String getName() { + return InspectionGadgetsBundle.message( + "unnecessary.javadoc.link.quickfix", tagName); + } + + @Override + protected void doFix(Project project, ProblemDescriptor descriptor) + throws IncorrectOperationException { + final PsiElement element = descriptor.getPsiElement(); + final PsiElement parent = element.getParent(); + if (!(parent instanceof PsiDocTag)) { + return; + } + final PsiDocTag docTag = (PsiDocTag)parent; + final PsiDocComment docComment = docTag.getContainingComment(); + if (docComment != null) { + if (shouldDeleteEntireComment(docComment)) { + docComment.delete(); + return; + } + } + docTag.delete(); + } + + private static boolean shouldDeleteEntireComment( + PsiDocComment docComment) { + final PsiDocToken[] docTokens = PsiTreeUtil.getChildrenOfType( + docComment, PsiDocToken.class); + if (docTokens == null) { + return false; + } + for (PsiDocToken docToken : docTokens) { + final IElementType tokenType = docToken.getTokenType(); + if (!JavaDocTokenType.DOC_COMMENT_DATA.equals(tokenType)) { + continue; + } + if (!StringUtil.isEmptyOrSpaces(docToken.getText())) { + return false; + } + } + return true; + } + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new UnnecessaryJavaDocLinkVisitor(); + } + + private class UnnecessaryJavaDocLinkVisitor + extends BaseInspectionVisitor { + + @Override + public void visitDocTag(PsiDocTag tag) { + super.visitDocTag(tag); + @NonNls final String name = tag.getName(); + if ("link".equals(name) || "linkplain".equals(name)) { + if (!(tag instanceof PsiInlineDocTag)) { + return; + } + } + else if ("see".equals(name)) { + if (tag instanceof PsiInlineDocTag) { + return; + } + } + final PsiReference reference = extractReference(tag); + if (reference == null) { + return; + } + final PsiElement target = reference.resolve(); + if (target == null) { + return; + } + final PsiMethod containingMethod = + PsiTreeUtil.getParentOfType(tag, PsiMethod.class); + if (containingMethod == null) { + return; + } + if (target.equals(containingMethod)) { + registerError(tag.getNameElement(), '@' + name, + Integer.valueOf(THIS_METHOD)); + return; + } + final PsiClass containingClass = + PsiTreeUtil.getParentOfType(tag, PsiClass.class); + if (target.equals(containingClass)) { + registerError(tag.getNameElement(), '@' + name, + Integer.valueOf(THIS_CLASS)); + return; + } + if (!(target instanceof PsiMethod)) { + return; + } + final PsiMethod method = (PsiMethod)target; + if (!isSuperMethod(method, containingMethod)) { + return; + } + if (ignoreInlineLinkToSuper && tag instanceof PsiInlineDocTag) { + return; + } + registerError(tag.getNameElement(), '@' + name, + Integer.valueOf(SUPER_METHOD)); + } + + private PsiReference extractReference(PsiDocTag tag) { + final PsiDocTagValue valueElement = tag.getValueElement(); + if (valueElement != null) { + return valueElement.getReference(); + } + // hack around the fact that a reference to a class is apparently + // not a PsiDocTagValue + final PsiElement[] dataElements = tag.getDataElements(); + if (dataElements.length == 0) { + return null; + } + PsiElement salientElement = null; + for (PsiElement dataElement : dataElements) { + if (!(dataElement instanceof PsiWhiteSpace)) { + salientElement = dataElement; + break; + } + } + if (salientElement == null) { + return null; + } + final PsiElement child = salientElement.getFirstChild(); + if (!(child instanceof PsiReference)) { + return null; + } + return (PsiReference)child; + } + + public boolean isSuperMethod(PsiMethod superMethodCandidate, + PsiMethod derivedMethod) { + final PsiClass superClassCandidate = + superMethodCandidate.getContainingClass(); + final PsiClass derivedClass = derivedMethod.getContainingClass(); + if (derivedClass == null || superClassCandidate == null) { + return false; + } + if (!derivedClass.isInheritor(superClassCandidate, false)) { + return false; + } + final PsiSubstitutor superSubstitutor = + TypeConversionUtil.getSuperClassSubstitutor( + superClassCandidate, derivedClass, + PsiSubstitutor.EMPTY); + final MethodSignature superSignature = + superMethodCandidate.getSignature(superSubstitutor); + final MethodSignature derivedSignature = + derivedMethod.getSignature(PsiSubstitutor.EMPTY); + return MethodSignatureUtil.isSubsignature(superSignature, + derivedSignature); + } + } +}
\ No newline at end of file |