blob: dda86130f4f29b8b88d65eb4cc60af0f85e64d51 [file] [log] [blame]
/*
* Copyright 2000-2009 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.
*/
/*
* User: anna
* Date: 24-Dec-2007
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.actions.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiVariableEx;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Generated;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.regex.Matcher;
public class SuppressManagerImpl extends SuppressManager {
@Override
@NotNull
public SuppressIntentionAction[] createSuppressActions(@NotNull final HighlightDisplayKey displayKey) {
return new SuppressIntentionAction[]{
new SuppressByJavaCommentFix(displayKey),
new SuppressLocalWithCommentFix(displayKey),
new SuppressParameterFix(displayKey),
new SuppressFix(displayKey),
new SuppressForClassFix(displayKey),
new SuppressAllForClassFix()
};
}
@Override
public boolean isSuppressedFor(@NotNull final PsiElement element, final String toolId) {
return getElementToolSuppressedIn(element, toolId) != null;
}
@Override
@Nullable
public PsiElement getElementMemberSuppressedIn(@NotNull final PsiDocCommentOwner owner, final String inspectionToolID) {
PsiElement element = getDocCommentToolSuppressedIn(owner, inspectionToolID);
if (element != null) return element;
element = getAnnotationMemberSuppressedIn(owner, inspectionToolID);
if (element != null) return element;
PsiDocCommentOwner classContainer = PsiTreeUtil.getParentOfType(owner, PsiDocCommentOwner.class);
while (classContainer != null) {
element = getDocCommentToolSuppressedIn(classContainer, inspectionToolID);
if (element != null) return element;
element = getAnnotationMemberSuppressedIn(classContainer, inspectionToolID);
if (element != null) return element;
classContainer = PsiTreeUtil.getParentOfType(classContainer, PsiDocCommentOwner.class);
}
return null;
}
@Override
@Nullable
public PsiElement getAnnotationMemberSuppressedIn(@NotNull final PsiModifierListOwner owner, final String inspectionToolID) {
final PsiAnnotation generatedAnnotation = AnnotationUtil.findAnnotation(owner, Generated.class.getName());
if (generatedAnnotation != null) return generatedAnnotation;
PsiModifierList modifierList = owner.getModifierList();
Collection<String> suppressedIds = getInspectionIdsSuppressedInAnnotation(modifierList);
for (String ids : suppressedIds) {
if (SuppressionUtil.isInspectionToolIdMentioned(ids, inspectionToolID)) {
return modifierList != null ? AnnotationUtil.findAnnotation(owner, SUPPRESS_INSPECTIONS_ANNOTATION_NAME) : null;
}
}
return null;
}
@Override
@Nullable
public PsiElement getDocCommentToolSuppressedIn(@NotNull final PsiDocCommentOwner owner, final String inspectionToolID) {
PsiDocComment docComment = owner.getDocComment();
if (docComment == null && owner.getParent() instanceof PsiDeclarationStatement) {
final PsiElement el = PsiTreeUtil.skipSiblingsBackward(owner.getParent(), PsiWhiteSpace.class);
if (el instanceof PsiDocComment) {
docComment = (PsiDocComment)el;
}
}
if (docComment != null) {
PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
if (inspectionTag != null) {
final PsiElement[] dataElements = inspectionTag.getDataElements();
for (PsiElement dataElement : dataElements) {
String valueText = dataElement.getText();
if (SuppressionUtil.isInspectionToolIdMentioned(valueText, inspectionToolID)) {
return docComment;
}
}
}
}
return null;
}
@Override
@NotNull
public Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull final PsiModifierListOwner owner) {
if (!PsiUtil.isLanguageLevel5OrHigher(owner)) return Collections.emptyList();
PsiModifierList modifierList = owner.getModifierList();
return getInspectionIdsSuppressedInAnnotation(modifierList);
}
@Override
@Nullable
public String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
if (element instanceof PsiComment) {
String text = element.getText();
Matcher matcher = SuppressionUtil.SUPPRESS_IN_LINE_COMMENT_PATTERN.matcher(text);
if (matcher.matches()) {
return matcher.group(1).trim();
}
}
if (element instanceof PsiDocCommentOwner) {
PsiDocComment docComment = ((PsiDocCommentOwner)element).getDocComment();
if (docComment != null) {
PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
if (inspectionTag != null) {
String valueText = "";
for (PsiElement dataElement : inspectionTag.getDataElements()) {
valueText += dataElement.getText();
}
return valueText;
}
}
}
if (element instanceof PsiModifierListOwner) {
Collection<String> suppressedIds = getInspectionIdsSuppressedInAnnotation((PsiModifierListOwner)element);
return suppressedIds.isEmpty() ? null : StringUtil.join(suppressedIds, ",");
}
return null;
}
@Override
@Nullable
public PsiElement getElementToolSuppressedIn(@NotNull final PsiElement place, final String toolId) {
if (place instanceof PsiFile) return null;
return ApplicationManager.getApplication().runReadAction(new Computable<PsiElement>() {
@Override
@Nullable
public PsiElement compute() {
final PsiElement statement = SuppressionUtil.getStatementToolSuppressedIn(place, toolId, PsiStatement.class);
if (statement != null) {
return statement;
}
PsiVariable local = PsiTreeUtil.getParentOfType(place, PsiVariable.class);
if (local != null && getAnnotationMemberSuppressedIn(local, toolId) != null) {
PsiModifierList modifierList = local.getModifierList();
return modifierList != null ? modifierList.findAnnotation(SUPPRESS_INSPECTIONS_ANNOTATION_NAME) : null;
}
PsiDocCommentOwner container = PsiTreeUtil.getNonStrictParentOfType(place, PsiDocCommentOwner.class);
while (true) {
if (!(container instanceof PsiTypeParameter)) break;
container = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class);
}
if (container != null) {
PsiElement element = getElementMemberSuppressedIn(container, toolId);
if (element != null) return element;
}
PsiDocCommentOwner classContainer = PsiTreeUtil.getParentOfType(container, PsiDocCommentOwner.class, true);
if (classContainer != null) {
PsiElement element = getElementMemberSuppressedIn(classContainer, toolId);
if (element != null) return element;
}
return null;
}
});
}
@NotNull
public static Collection<String> getInspectionIdsSuppressedInAnnotation(final PsiModifierList modifierList) {
if (modifierList == null) {
return Collections.emptyList();
}
final PsiModifierListOwner owner = (PsiModifierListOwner)modifierList.getParent();
PsiAnnotation annotation = AnnotationUtil.findAnnotation(owner, SUPPRESS_INSPECTIONS_ANNOTATION_NAME);
if (annotation == null) {
return Collections.emptyList();
}
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
if (attributes.length == 0) {
return Collections.emptyList();
}
final PsiAnnotationMemberValue attributeValue = attributes[0].getValue();
Collection<String> result = new ArrayList<String>();
if (attributeValue instanceof PsiArrayInitializerMemberValue) {
final PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)attributeValue).getInitializers();
for (PsiAnnotationMemberValue annotationMemberValue : initializers) {
final String id = getInspectionIdSuppressedInAnnotationAttribute(annotationMemberValue);
if (id != null) {
result.add(id);
}
}
}
else {
final String id = getInspectionIdSuppressedInAnnotationAttribute(attributeValue);
if (id != null) {
result.add(id);
}
}
return result;
}
@Nullable
public static String getInspectionIdSuppressedInAnnotationAttribute(PsiElement element) {
if (element instanceof PsiLiteralExpression) {
final Object value = ((PsiLiteralExpression)element).getValue();
if (value instanceof String) {
return (String)value;
}
}
else if (element instanceof PsiReferenceExpression) {
final PsiElement psiElement = ((PsiReferenceExpression)element).resolve();
if (psiElement instanceof PsiVariableEx) {
final Object val = ((PsiVariableEx)psiElement).computeConstantValue(new HashSet<PsiVariable>());
if (val instanceof String) {
return (String)val;
}
}
}
return null;
}
@Override
public boolean canHave15Suppressions(@NotNull final PsiElement file) {
final Module module = ModuleUtilCore.findModuleForPsiElement(file);
if (module == null) return false;
final Sdk jdk = ModuleRootManager.getInstance(module).getSdk();
if (jdk == null) return false;
final boolean is_1_5 = JavaSdk.getInstance().isOfVersionOrHigher(jdk, JavaSdkVersion.JDK_1_5);
return DaemonCodeAnalyzerSettings.getInstance().SUPPRESS_WARNINGS && is_1_5 && PsiUtil.isLanguageLevel5OrHigher(file);
}
@Override
public boolean alreadyHas14Suppressions(@NotNull final PsiDocCommentOwner commentOwner) {
final PsiDocComment docComment = commentOwner.getDocComment();
return docComment != null && docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME) != null;
}
}