summaryrefslogtreecommitdiff
path: root/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2013-05-31 07:45:51 -0700
committerTor Norbye <tnorbye@google.com>2013-05-31 07:45:51 -0700
commitec3fb1e06285c0467a7a20360ca80453bc7635d4 (patch)
tree2402cdec34611f34b8385ff45387d6734bf6f994 /plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc
parenta6eac331b3d9f0d4168b12356ea256c83f4e9c05 (diff)
downloadidea-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')
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/HtmlTagCanBeJavadocTagInspection.java184
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryInheritDocInspection.java120
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/UnnecessaryJavaDocLinkInspection.java253
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, "}", "&#125;"));
+ newCommentText.append('}');
+ newCommentText.append(text.substring(endIndex + 7));
+ }
+ else {
+ final String codeText = text.substring(startIndex + 6);
+ newCommentText.append(codeText);
+ //StringUtil.replace(codeText, "}", "&#125;"));
+ 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