diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaChangeLocalityDetector.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaChangeLocalityDetector.java
index 6a8f8244faca..1f06435e398a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaChangeLocalityDetector.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaChangeLocalityDetector.java
@@ -21,15 +21,20 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeInsight.daemon.ChangeLocalityDetector;
import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class JavaChangeLocalityDetector implements ChangeLocalityDetector {
@Override
@Nullable
- public PsiElement getChangeHighlightingDirtyScopeFor(final PsiElement element) {
+ public PsiElement getChangeHighlightingDirtyScopeFor(@NotNull final PsiElement element) {
+ // optimization
PsiElement parent = element.getParent();
- if (element instanceof PsiCodeBlock && parent instanceof PsiMethod && !((PsiMethod)parent).isConstructor() &&
- parent.getParent() instanceof PsiClass && !(parent.getParent() instanceof PsiAnonymousClass)) {
+ if (element instanceof PsiCodeBlock
+ && parent instanceof PsiMethod
+ && !((PsiMethod)parent).isConstructor()
+ && parent.getParent() instanceof PsiClass
+ && !(parent.getParent() instanceof PsiAnonymousClass)) {
// for changes inside method, rehighlight codeblock only
// do not use this optimization for constructors and class initializers - to update non-initialized fields
return parent;
diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java
index b80a4b6fc9be..fedbd19f2f48 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java
@@ -20,9 +20,17 @@
package com.intellij.codeInsight.daemon;
import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface ChangeLocalityDetector {
+ /**
+ * @param changedElement
+ * @return the psi element (ancestor of the changedElement) which should be re-highlighted, or null if unsure.
+ * e.g. in Java we re-highlight enclosing code block only when element inside has changed.
+ * Note: do not traverse PSI tree upwards here,
+ * since this ChangeLocalityDetector will be called for the changed element and all its parents anyway.
+ */
@Nullable
- PsiElement getChangeHighlightingDirtyScopeFor(PsiElement changedElement);
+ PsiElement getChangeHighlightingDirtyScopeFor(@NotNull PsiElement changedElement);
}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultChangeLocalityDetector.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultChangeLocalityDetector.java
new file mode 100644
index 000000000000..a822811aa845
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultChangeLocalityDetector.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2012 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.
+ */
+package com.intellij.codeInsight.daemon.impl;
+
+import com.intellij.codeInsight.daemon.ChangeLocalityDetector;
+import com.intellij.codeInspection.SuppressionUtil;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
+import org.jetbrains.annotations.NotNull;
+
+public class DefaultChangeLocalityDetector implements ChangeLocalityDetector {
+ @Override
+ public PsiElement getChangeHighlightingDirtyScopeFor(@NotNull PsiElement changedElement) {
+ if (changedElement instanceof PsiWhiteSpace ||
+ changedElement instanceof PsiComment
+ && !changedElement.getText().contains(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME)) {
+ return changedElement;
+ }
+ return null;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java
index f148691cd732..956f39823ba5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java
@@ -17,7 +17,6 @@
package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeInsight.daemon.ChangeLocalityDetector;
-import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
@@ -214,18 +213,9 @@ public class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable
return;
}
- // optimization
- if (whitespaceOptimizationAllowed && UpdateHighlightersUtil.isWhitespaceOptimizationAllowed(document)) {
- if (child instanceof PsiWhiteSpace ||
- child instanceof PsiComment && !child.getText().contains(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME)) {
- myFileStatusMap.markFileScopeDirty(document, child.getTextRange(), fileLength);
- return;
- }
- }
-
- PsiElement element = child;
+ PsiElement element = whitespaceOptimizationAllowed && UpdateHighlightersUtil.isWhitespaceOptimizationAllowed(document) ? child : child.getParent();
while (true) {
- if (element instanceof PsiFile || element instanceof PsiDirectory) {
+ if (element == null || element instanceof PsiFile || element instanceof PsiDirectory) {
myFileStatusMap.markAllFilesDirty();
return;
}
@@ -242,10 +232,18 @@ public class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable
@Nullable
private static PsiElement getChangeHighlightingScope(PsiElement element) {
+ DefaultChangeLocalityDetector defaultDetector = null;
for (ChangeLocalityDetector detector : Extensions.getExtensions(EP_NAME)) {
+ if (detector instanceof DefaultChangeLocalityDetector) {
+ // run default detector last
+ assert defaultDetector == null : defaultDetector;
+ defaultDetector = (DefaultChangeLocalityDetector)detector;
+ continue;
+ }
final PsiElement scope = detector.getChangeHighlightingDirtyScopeFor(element);
if (scope != null) return scope;
}
- return null;
+ assert defaultDetector != null : "com.intellij.codeInsight.daemon.impl.DefaultChangeLocalityDetector is unregistered";
+ return defaultDetector.getChangeHighlightingDirtyScopeFor(element);
}
}
diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml
index 6465f1f168f9..834e6e03ed0c 100644
--- a/platform/platform-resources/src/META-INF/XmlPlugin.xml
+++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml
@@ -404,7 +404,7 @@
-
+
+
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltChangeLocalityDetector.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltChangeLocalityDetector.java
index c72f6ac58eb8..5b7dedcecae3 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltChangeLocalityDetector.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltChangeLocalityDetector.java
@@ -22,6 +22,7 @@ import com.intellij.psi.xml.XmlElementType;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlToken;
import org.intellij.lang.xpath.xslt.XsltSupport;
+import org.jetbrains.annotations.NotNull;
/*
* Created by IntelliJ IDEA.
@@ -30,7 +31,7 @@ import org.intellij.lang.xpath.xslt.XsltSupport;
*/
public class XsltChangeLocalityDetector implements ChangeLocalityDetector {
@Override
- public PsiElement getChangeHighlightingDirtyScopeFor(PsiElement changedElement) {
+ public PsiElement getChangeHighlightingDirtyScopeFor(@NotNull PsiElement changedElement) {
try {
if (changedElement instanceof XmlToken && changedElement.getNode().getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN) {
final PsiElement grandParent = changedElement.getParent().getParent();
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index cb3175edc39c..82372a8498d0 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -969,6 +969,7 @@
+
diff --git a/xml/impl/src/com/intellij/xml/XmlChangeLocalityDetector.java b/xml/impl/src/com/intellij/xml/XmlChangeLocalityDetector.java
new file mode 100644
index 000000000000..fb65aa55965d
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/XmlChangeLocalityDetector.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 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.
+ */
+package com.intellij.xml;
+
+import com.intellij.codeInsight.daemon.ChangeLocalityDetector;
+import com.intellij.codeInspection.DefaultXmlSuppressionProvider;
+import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+public class XmlChangeLocalityDetector implements ChangeLocalityDetector {
+ @Override
+ public PsiElement getChangeHighlightingDirtyScopeFor(@NotNull PsiElement changedElement) {
+ // rehighlight everything when inspection suppress comment changed
+ if (changedElement.getLanguage() instanceof XMLLanguage
+ && changedElement instanceof PsiComment
+ && changedElement.getText().contains(DefaultXmlSuppressionProvider.SUPPRESS_MARK)) {
+ return changedElement.getContainingFile();
+ }
+ return null;
+ }
+}
diff --git a/xml/openapi/src/com/intellij/codeInspection/DefaultXmlSuppressionProvider.java b/xml/openapi/src/com/intellij/codeInspection/DefaultXmlSuppressionProvider.java
index f1ce3969dfc2..6aa1a22ad909 100644
--- a/xml/openapi/src/com/intellij/codeInspection/DefaultXmlSuppressionProvider.java
+++ b/xml/openapi/src/com/intellij/codeInspection/DefaultXmlSuppressionProvider.java
@@ -37,16 +37,20 @@ import org.jetbrains.annotations.Nullable;
*/
public class DefaultXmlSuppressionProvider extends XmlSuppressionProvider {
+ public static final String SUPPRESS_MARK = "suppress";
+
@Override
public boolean isProviderAvailable(PsiFile file) {
return true;
}
+ @Override
public boolean isSuppressedFor(PsiElement element, String inspectionId) {
final XmlTag tag = element instanceof XmlFile ? ((XmlFile)element).getRootTag() : PsiTreeUtil.getContextOfType(element, XmlTag.class, false);
return tag != null && findSuppression(tag, inspectionId, element) != null;
}
+ @Override
public void suppressForFile(PsiElement element, String inspectionId) {
final PsiFile file = element.getContainingFile();
final XmlDocument document = ((XmlFile)file).getDocument();
@@ -55,6 +59,7 @@ public class DefaultXmlSuppressionProvider extends XmlSuppressionProvider {
suppress(file, findFileSuppression(anchor, null, element), inspectionId, anchor.getTextRange().getStartOffset());
}
+ @Override
public void suppressForTag(PsiElement element, String inspectionId) {
final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
assert tag != null;
@@ -140,7 +145,9 @@ public class DefaultXmlSuppressionProvider extends XmlSuppressionProvider {
@NonNls
protected String getPrefix() {
- return "