2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.intellij
.codeInspection
;
19 import com
.intellij
.openapi
.command
.undo
.UndoUtil
;
20 import com
.intellij
.openapi
.editor
.Document
;
21 import com
.intellij
.openapi
.project
.Project
;
22 import com
.intellij
.openapi
.util
.TextRange
;
23 import com
.intellij
.psi
.PsiComment
;
24 import com
.intellij
.psi
.PsiDocumentManager
;
25 import com
.intellij
.psi
.PsiElement
;
26 import com
.intellij
.psi
.PsiFile
;
27 import com
.intellij
.psi
.codeStyle
.CodeStyleManager
;
28 import com
.intellij
.psi
.util
.PsiTreeUtil
;
29 import com
.intellij
.psi
.xml
.*;
30 import com
.intellij
.refactoring
.util
.CommonRefactoringUtil
;
31 import com
.intellij
.util
.ArrayUtil
;
32 import org
.jetbrains
.annotations
.NonNls
;
33 import org
.jetbrains
.annotations
.Nullable
;
36 * @author Dmitry Avdeev
38 public class DefaultXmlSuppressionProvider
extends XmlSuppressionProvider
{
41 public boolean isProviderAvailable(PsiFile file
) {
45 public boolean isSuppressedFor(PsiElement element
, String inspectionId
) {
46 final XmlTag tag
= PsiTreeUtil
.getContextOfType(element
, XmlTag
.class, false);
47 return tag
!= null && findSuppression(tag
, inspectionId
, element
) != null;
50 public void suppressForFile(PsiElement element
, String inspectionId
) {
51 final PsiFile file
= element
.getContainingFile();
52 final XmlDocument document
= ((XmlFile
)file
).getDocument();
53 final PsiElement anchor
= document
!= null ? document
.getRootTag() : file
.findElementAt(0);
54 assert anchor
!= null;
55 suppress(file
, findFileSuppression(anchor
, null, element
), inspectionId
, anchor
.getTextRange().getStartOffset());
58 public void suppressForTag(PsiElement element
, String inspectionId
) {
59 final XmlTag tag
= PsiTreeUtil
.getParentOfType(element
, XmlTag
.class);
61 suppress(element
.getContainingFile(), findSuppressionLeaf(tag
, null, 0), inspectionId
, tag
.getTextRange().getStartOffset());
65 protected PsiElement
findSuppression(final PsiElement anchor
, final String id
, PsiElement originalElement
) {
66 final PsiElement element
= findSuppressionLeaf(anchor
, id
, 0);
67 if (element
!= null) return element
;
69 return findFileSuppression(anchor
, id
, originalElement
);
73 protected PsiElement
findFileSuppression(PsiElement anchor
, String id
, PsiElement originalElement
) {
74 final PsiFile file
= anchor
.getContainingFile();
75 if (file
instanceof XmlFile
) {
76 final XmlDocument document
= ((XmlFile
)file
).getDocument();
77 final XmlTag rootTag
= document
!= null ? document
.getRootTag() : null;
78 PsiElement leaf
= rootTag
!= null ? rootTag
.getPrevSibling() : file
.findElementAt(0);
79 return findSuppressionLeaf(leaf
, id
, 0);
85 protected PsiElement
findSuppressionLeaf(PsiElement leaf
, @Nullable final String id
, int offset
) {
86 while (leaf
!= null && leaf
.getTextOffset() >= offset
) {
87 if (leaf
instanceof PsiComment
|| leaf
instanceof XmlProlog
|| leaf
instanceof XmlText
) {
88 @NonNls String text
= leaf
.getText();
89 if (isSuppressedFor(text
, id
)) return leaf
;
91 leaf
= leaf
.getPrevSibling();
92 if (leaf
instanceof XmlTag
) {
99 private boolean isSuppressedFor(@NonNls final String text
, @Nullable final String id
) {
100 if (!text
.contains(getPrefix())) {
106 @NonNls final String
[] parts
= text
.split("[ ,]");
107 return ArrayUtil
.find(parts
, id
) != -1 || ArrayUtil
.find(parts
, XmlSuppressableInspectionTool
.ALL
) != -1;
110 protected void suppress(PsiFile file
, final PsiElement suppressionElement
, String inspectionId
, final int offset
) {
111 final Project project
= file
.getProject();
112 if (!CommonRefactoringUtil
.checkReadOnlyStatus(file
)) {
115 final Document doc
= PsiDocumentManager
.getInstance(project
).getDocument(file
);
118 if (suppressionElement
!= null) {
119 final TextRange textRange
= suppressionElement
.getTextRange();
120 String text
= suppressionElement
.getText();
121 final String suppressionText
= getSuppressionText(inspectionId
, text
);
122 doc
.replaceString(textRange
.getStartOffset(), textRange
.getEndOffset(), suppressionText
);
124 final String suppressionText
= getSuppressionText(inspectionId
, null);
125 doc
.insertString(offset
, suppressionText
);
126 CodeStyleManager
.getInstance(project
).adjustLineIndent(doc
, offset
+ suppressionText
.length());
127 UndoUtil
.markPsiFileForUndo(file
);
131 protected String
getSuppressionText(String inspectionId
, @Nullable String originalText
) {
132 if (originalText
== null) {
133 return getPrefix() + inspectionId
+ getSuffix();
134 } else if (inspectionId
.equals(XmlSuppressableInspectionTool
.ALL
)) {
135 final int pos
= originalText
.indexOf(getPrefix());
136 return originalText
.substring(0, pos
) + getPrefix() + inspectionId
+ getSuffix();
138 return originalText
.replace(getSuffix(), ", " + inspectionId
+ getSuffix());
142 protected String
getPrefix() {
143 return "<!--suppress ";
147 protected String
getSuffix() {