TreeChangePreprocessorBase: extract common code and simplify

This commit is contained in:
Gregory.Shrago
2017-01-21 17:10:29 +03:00
parent 2dd83a202d
commit c224b34de7
7 changed files with 118 additions and 117 deletions
@@ -17,34 +17,24 @@ package com.intellij.json.psi.impl;
import com.intellij.json.JsonLanguage;
import com.intellij.json.psi.JsonFile;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.psi.impl.PsiTreeChangePreprocessorBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class JsonTreeChangePreprocessor extends PsiTreeChangePreprocessorBase {
public JsonTreeChangePreprocessor(@NotNull Project project) {
super(project);
public JsonTreeChangePreprocessor(@NotNull PsiManager psiManager) {
super(psiManager);
}
@Override
public void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
if (event.getFile() instanceof JsonFile) {
super.treeChanged(event);
}
protected boolean acceptsEvent(@NotNull PsiTreeChangeEventImpl event) {
return event.getFile() instanceof JsonFile;
}
@Override
protected boolean isInsideCodeBlock(@Nullable PsiElement element) {
if (element instanceof PsiFileSystemItem) {
return false;
}
if (element == null || element.getParent() == null) {
return true;
}
return !(element.getLanguage() instanceof JsonLanguage);
protected boolean isOutOfCodeBlock(@NotNull PsiElement element) {
return element.getLanguage() instanceof JsonLanguage;
}
}
@@ -40,7 +40,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -86,7 +85,6 @@ public class PsiManagerImpl extends PsiManagerEx {
myFileManager = isProjectDefault ? new EmptyFileManager(this) : new FileManagerImpl(this, fileDocumentManager, fileIndex);
myTreeChangePreprocessors.add((PsiTreeChangePreprocessor)modificationTracker);
Collections.addAll(myTreeChangePreprocessors, Extensions.getExtensions(PsiTreeChangePreprocessor.EP_NAME, myProject));
Disposer.register(project, new Disposable() {
@Override
@@ -361,6 +359,9 @@ public class PsiManagerImpl extends PsiManagerEx {
for (PsiTreeChangePreprocessor preprocessor : myTreeChangePreprocessors) {
preprocessor.treeChanged(event);
}
for (PsiTreeChangePreprocessor preprocessor : Extensions.getExtensions(PsiTreeChangePreprocessor.EP_NAME, myProject)) {
preprocessor.treeChanged(event);
}
for (PsiTreeChangeListener listener : myTreeChangeListeners) {
try {
@@ -29,6 +29,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.atomic.AtomicLong;
import static com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.CHILD_MOVED;
import static com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.PROPERTY_CHANGED;
/**
* @author mike
* Date: Jul 18, 2002
@@ -88,12 +91,17 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
return;
}
PsiTreeChangeEventImpl.PsiEventType code = event.getCode();
boolean outOfCodeBlock =
code == PROPERTY_CHANGED ? event.getPropertyName() == PsiTreeChangeEvent.PROP_UNLOADED_PSI :
code == CHILD_MOVED ? event.getOldParent() instanceof PsiDirectory || event.getNewParent() instanceof PsiDirectory :
event.getParent() instanceof PsiDirectory;
myModificationCount.getAndIncrement();
if (event.getParent() instanceof PsiDirectory
|| event.getOldParent() instanceof PsiDirectory /* move events */) {
if (outOfCodeBlock) {
myJavaStructureModificationCount.getAndIncrement();
myOutOfCodeBlockModificationCount.getAndIncrement();
}
fireEvent();
}
@@ -16,84 +16,111 @@
package com.intellij.psi.impl;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class PsiTreeChangePreprocessorBase implements PsiTreeChangePreprocessor {
@NotNull private final Project myProject;
public PsiTreeChangePreprocessorBase(@NotNull Project project) {
myProject = project;
protected final PsiManager myPsiManager;
public PsiTreeChangePreprocessorBase(@NotNull PsiManager psiManager) {
myPsiManager = psiManager;
}
@NotNull
protected Project getProject() {
return myProject;
protected abstract boolean acceptsEvent(@NotNull PsiTreeChangeEventImpl event);
/**
* Shall return true <em>if and only if</em> the element is considered to be "out of code block"
* (the exact meaning is language- or technology-specific); otherwise false.
*
* @see PsiModificationTrackerImpl#getOutOfCodeBlockModificationCount()
*/
protected abstract boolean isOutOfCodeBlock(@NotNull PsiElement element);
protected boolean isOutOfCodeBlock(@NotNull PsiFileSystemItem file) {
return true;
}
protected boolean isOutOfCodeBlockInvalid(@NotNull PsiElement element) {
return false;
}
private boolean outOfCodeBlock(@Nullable PsiElement element) {
if (element == null) return false;
if (element instanceof PsiDirectory) return false; // handled by PsiModificationTrackerImpl#treeChanged()
if (!element.isValid()) return !(element instanceof PsiFileSystemItem) && isOutOfCodeBlockInvalid(element);
if (element instanceof PsiFileSystemItem) return isOutOfCodeBlock((PsiFileSystemItem)element);
return isOutOfCodeBlock(element);
}
@Override
public void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
public final void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
if (!PsiModificationTrackerImpl.canAffectPsi(event)) {
return;
}
if (!acceptsEvent(event)) {
return;
}
onTreeChanged(event);
}
boolean changedInsideCodeBlock = false;
protected void onTreeChanged(@NotNull PsiTreeChangeEventImpl event) {
boolean outOfCodeBlock;
switch (event.getCode()) {
case BEFORE_CHILDREN_CHANGE:
if (event.getParent() instanceof PsiFile) {
changedInsideCodeBlock = true;
break; // May be caused by fake PSI event from PomTransaction. A real event will anyway follow.
}
case BEFORE_PROPERTY_CHANGE:
case BEFORE_CHILD_MOVEMENT:
case BEFORE_CHILD_ADDITION:
case BEFORE_CHILD_REMOVAL:
case BEFORE_CHILD_REPLACEMENT:
outOfCodeBlock = false;
break;
case BEFORE_CHILDREN_CHANGE:
case CHILDREN_CHANGED:
if (event.isGenericChange()) {
return;
}
changedInsideCodeBlock = isInsideCodeBlock(event.getParent());
outOfCodeBlock = outOfCodeBlock(event.getParent());
break;
case BEFORE_CHILD_ADDITION:
case BEFORE_CHILD_REMOVAL:
case CHILD_ADDED:
case CHILD_REMOVED:
case BEFORE_CHILD_REPLACEMENT:
case CHILD_REPLACED :
changedInsideCodeBlock = isInsideCodeBlock(event.getParent()) &&
isInsideCodeBlock(event.getChild()) &&
isInsideCodeBlock(event.getOldChild()) &&
isInsideCodeBlock(event.getNewChild());
case CHILD_REPLACED:
outOfCodeBlock = outOfCodeBlock(event.getParent()) ||
outOfCodeBlock(event.getChild()) ||
outOfCodeBlock(event.getOldChild()) ||
outOfCodeBlock(event.getNewChild());
break;
case BEFORE_PROPERTY_CHANGE:
case PROPERTY_CHANGED:
changedInsideCodeBlock = false;
outOfCodeBlock = true;
break;
case BEFORE_CHILD_MOVEMENT:
case CHILD_MOVED:
changedInsideCodeBlock = isInsideCodeBlock(event.getOldParent()) &&
isInsideCodeBlock(event.getNewParent()) &&
isInsideCodeBlock(event.getChild());
outOfCodeBlock = outOfCodeBlock(event.getOldParent()) ||
outOfCodeBlock(event.getNewParent()) ||
outOfCodeBlock(event.getChild());
break;
default:
outOfCodeBlock = true;
break;
}
if (!changedInsideCodeBlock) {
processOutOfCodeBlockModification(event);
if (outOfCodeBlock) {
onOutOfCodeBlockModification(event);
doIncOutOfCodeBlockCounter();
}
}
@NotNull
private PsiModificationTrackerImpl getModificationTracker() {
return (PsiModificationTrackerImpl)PsiManager.getInstance(myProject).getModificationTracker();
protected void onOutOfCodeBlockModification(@NotNull PsiTreeChangeEventImpl event) {
}
protected void processOutOfCodeBlockModification(final PsiTreeChangeEventImpl event) {
getModificationTracker().incOutOfCodeBlockModificationCounter();
protected void doIncOutOfCodeBlockCounter() {
((PsiModificationTrackerImpl)myPsiManager.getModificationTracker()).incOutOfCodeBlockModificationCounter();
}
protected abstract boolean isInsideCodeBlock(PsiElement element);
}
@@ -1,10 +1,9 @@
package org.jetbrains.yaml.psi;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.psi.impl.PsiTreeChangePreprocessorBase;
import org.jetbrains.annotations.NotNull;
@@ -13,41 +12,33 @@ import org.jetbrains.annotations.NotNull;
* @author oleg
*/
final class YAMLPsiManager extends PsiTreeChangePreprocessorBase {
public YAMLPsiManager(@NotNull Project project) {
super(project);
public YAMLPsiManager(@NotNull PsiManager psiManager) {
super(psiManager);
}
@Override
protected boolean isInsideCodeBlock(PsiElement element) {
if (element instanceof PsiFileSystemItem) {
return false;
}
if (element == null || element.getParent() == null) {
return true;
}
protected boolean acceptsEvent(@NotNull PsiTreeChangeEventImpl event) {
return event.getFile() instanceof YAMLFile;
}
@Override
protected boolean isOutOfCodeBlock(@NotNull PsiElement element) {
while (true) {
if (element instanceof YAMLFile) {
return false;
return true;
}
if (element instanceof PsiFile || element instanceof PsiDirectory) {
return true;
return false;
}
PsiElement parent = element.getParent();
if (!(parent instanceof YAMLFile ||
parent instanceof YAMLKeyValue ||
parent instanceof YAMLCompoundValue ||
parent instanceof YAMLDocument)) {
return true;
return false;
}
element = parent;
}
}
@Override
public void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
if (!(event.getFile() instanceof YAMLFile)) return;
super.treeChanged(event);
}
}
@@ -15,11 +15,10 @@
*/
package com.jetbrains.python;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.psi.impl.PsiTreeChangePreprocessorBase;
import com.jetbrains.python.psi.PyFile;
@@ -27,34 +26,27 @@ import com.jetbrains.python.psi.PyFunction;
import org.jetbrains.annotations.NotNull;
public class PythonPsiManager extends PsiTreeChangePreprocessorBase {
public PythonPsiManager(@NotNull Project project) {
super(project);
public PythonPsiManager(@NotNull PsiManager psiManager) {
super(psiManager);
}
public void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
if (event.getFile() instanceof PyFile) {
super.treeChanged(event);
}
@Override
protected boolean acceptsEvent(@NotNull PsiTreeChangeEventImpl event) {
return event.getFile() instanceof PyFile;
}
protected boolean isInsideCodeBlock(PsiElement element) {
if (element instanceof PsiFileSystemItem) {
return false;
}
if (element == null || !element.isValid() || element.getParent() == null) return true;
protected boolean isOutOfCodeBlock(@NotNull PsiElement element) {
while (true) {
if (element instanceof PyFile) {
return false;
return true;
}
if (element instanceof PsiFile || element instanceof PsiDirectory || element == null) {
return true;
return false;
}
PsiElement pparent = element.getParent();
if (pparent instanceof PyFunction) {
final PyFunction pyFunction = (PyFunction)pparent;
return !(element == pyFunction.getParameterList() || element == pyFunction.getNameIdentifier());
PyFunction pyFunction = (PyFunction)pparent;
return element == pyFunction.getParameterList() || element == pyFunction.getNameIdentifier();
}
element = pparent;
}
@@ -1,36 +1,28 @@
package com.intellij.xml;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.psi.impl.PsiTreeChangePreprocessorBase;
import com.intellij.psi.xml.XmlFile;
import org.jetbrains.annotations.NotNull;
public class XmlPsiTreeChangePreprocessor extends PsiTreeChangePreprocessorBase {
public XmlPsiTreeChangePreprocessor(@NotNull Project project) {
super(project);
public XmlPsiTreeChangePreprocessor(@NotNull PsiManager psiManager) {
super(psiManager);
}
@Override
protected boolean isInsideCodeBlock(PsiElement element) {
if (element instanceof PsiFileSystemItem) {
return false;
}
protected boolean acceptsEvent(@NotNull PsiTreeChangeEventImpl event) {
return event.getFile() instanceof XmlFile;
}
if (element == null || element.getParent() == null) return true;
final boolean isXml = element.getLanguage() instanceof XMLLanguage;
@Override
protected boolean isOutOfCodeBlock(@NotNull PsiElement element) {
// any xml element isn't inside a "code block"
// cause we display even attributes and tag values in structure view
return !isXml;
return element.getLanguage() instanceof XMLLanguage;
}
@Override
public void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
if (!(event.getFile() instanceof XmlFile)) return;
super.treeChanged(event);
}
}