diff --git a/pom/src/com/intellij/pom/tree/TreeAspect.java b/pom/src/com/intellij/pom/tree/TreeAspect.java new file mode 100644 index 000000000000..6c20bf5ccaad --- /dev/null +++ b/pom/src/com/intellij/pom/tree/TreeAspect.java @@ -0,0 +1,27 @@ +package com.intellij.pom.tree; + +import com.intellij.pom.PomModel; +import com.intellij.pom.PomModelAspect; +import com.intellij.pom.event.PomModelEvent; + +import java.util.Collections; +import java.util.Set; + +public class TreeAspect implements PomModelAspect{ + private final PomModel myModel; + + public TreeAspect(PomModel model) { + myModel = model; + myModel.registerAspect(this, (Set)Collections.EMPTY_SET); + } + + public void projectOpened() {} + public void projectClosed() {} + public void initComponent() {} + public void disposeComponent() {} + public void update(PomModelEvent event) {} + + public String getComponentName() { + return "Tree POM aspect"; + } +} diff --git a/pom/src/com/intellij/pom/tree/TreeAspectEvent.java b/pom/src/com/intellij/pom/tree/TreeAspectEvent.java new file mode 100644 index 000000000000..b56aaf12e981 --- /dev/null +++ b/pom/src/com/intellij/pom/tree/TreeAspectEvent.java @@ -0,0 +1,12 @@ +package com.intellij.pom.tree; + +import com.intellij.pom.PomModel; +import com.intellij.pom.event.PomModelEvent; +import com.intellij.pom.tree.events.TreeChangeEvent; + +public class TreeAspectEvent extends PomModelEvent { + public TreeAspectEvent(PomModel model, TreeChangeEvent reparseAccumulatedEvent) { + super(model); + registerChangeSet(model.getModelAspect(TreeAspect.class), reparseAccumulatedEvent); + } +} diff --git a/pom/src/com/intellij/pom/tree/events/ChangeInfo.java b/pom/src/com/intellij/pom/tree/events/ChangeInfo.java new file mode 100644 index 000000000000..295b9f454861 --- /dev/null +++ b/pom/src/com/intellij/pom/tree/events/ChangeInfo.java @@ -0,0 +1,11 @@ +package com.intellij.pom.tree.events; + +public interface ChangeInfo { + short ADD = 0; + short REMOVED = 1; + short REPLACE = 2; + short CONTENTS_CHANGED = 3; + + int getChangeType(); + int getOldLength(); +} diff --git a/pom/src/com/intellij/pom/tree/events/ReplaceChangeInfo.java b/pom/src/com/intellij/pom/tree/events/ReplaceChangeInfo.java new file mode 100644 index 000000000000..744c78a54e84 --- /dev/null +++ b/pom/src/com/intellij/pom/tree/events/ReplaceChangeInfo.java @@ -0,0 +1,7 @@ +package com.intellij.pom.tree.events; + +import com.intellij.lang.ASTNode; + +public interface ReplaceChangeInfo { + ASTNode getReplaced(); +} diff --git a/pom/src/com/intellij/pom/tree/events/TreeChange.java b/pom/src/com/intellij/pom/tree/events/TreeChange.java new file mode 100644 index 000000000000..01daed7b3561 --- /dev/null +++ b/pom/src/com/intellij/pom/tree/events/TreeChange.java @@ -0,0 +1,23 @@ +package com.intellij.pom.tree.events; + +import com.intellij.lang.ASTNode; + +/** + * Created by IntelliJ IDEA. + * User: ik + * Date: Oct 6, 2004 + * Time: 11:00:28 PM + * To change this template use File | Settings | File Templates. + */ + +public interface TreeChange { + void addChange(ASTNode child, ChangeInfo changeInfo); + + ASTNode[] getAffectedChildren(); + ChangeInfo getChangeByChild(ASTNode child); + + void composite(TreeChange treeChange); + boolean isEmpty(); + + void removeChange(ASTNode beforeEqualDepth); +} diff --git a/pom/src/com/intellij/pom/tree/events/TreeChangeEvent.java b/pom/src/com/intellij/pom/tree/events/TreeChangeEvent.java new file mode 100644 index 000000000000..9a87a258c719 --- /dev/null +++ b/pom/src/com/intellij/pom/tree/events/TreeChangeEvent.java @@ -0,0 +1,20 @@ +package com.intellij.pom.tree.events; + +import com.intellij.lang.ASTNode; +import com.intellij.pom.event.PomChangeSet; + +/** + * Created by IntelliJ IDEA. + * User: ik + * Date: Oct 6, 2004 + * Time: 10:56:52 PM + * To change this template use File | Settings | File Templates. + */ +public interface TreeChangeEvent extends PomChangeSet{ + ASTNode getRootElement(); + ASTNode[] getChangedElements(); + TreeChange getChangesByElement(ASTNode element); + + void addElementaryChange(ASTNode child, ChangeInfo change); + void clear(); +} diff --git a/pom/src/com/intellij/pom/xml/XmlAspect.java b/pom/src/com/intellij/pom/xml/XmlAspect.java new file mode 100644 index 000000000000..ce51c050e550 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/XmlAspect.java @@ -0,0 +1,6 @@ +package com.intellij.pom.xml; + +import com.intellij.pom.PomModelAspect; + +public interface XmlAspect extends PomModelAspect { +} diff --git a/pom/src/com/intellij/pom/xml/XmlChangeSet.java b/pom/src/com/intellij/pom/xml/XmlChangeSet.java new file mode 100644 index 000000000000..f3f7c0a281c7 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/XmlChangeSet.java @@ -0,0 +1,18 @@ +package com.intellij.pom.xml; + +import com.intellij.pom.event.PomChangeSet; +import com.intellij.pom.PomModelAspect; +import com.intellij.pom.xml.impl.events.XmlChange; +import com.intellij.psi.xml.XmlFile; + +public interface XmlChangeSet extends PomChangeSet { + XmlChange[] getChanges(); + + PomModelAspect getAspect(); + + void add(XmlChange xmlChange); + + void clear(); + + XmlFile getChangedFile(); +} diff --git a/pom/src/com/intellij/pom/xml/XmlChangeVisitor.java b/pom/src/com/intellij/pom/xml/XmlChangeVisitor.java new file mode 100644 index 000000000000..3c60bda449e8 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/XmlChangeVisitor.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved. + * Use is subject to license terms. + */ + +package com.intellij.pom.xml; + +import com.intellij.pom.xml.impl.events.*; + +/** + * @author peter + */ +public interface XmlChangeVisitor { + void visitXmlAttributeSet(final XmlAttributeSet xmlAttributeSet); + + void visitDocumentChanged(final XmlDocumentChanged xmlDocumentChangedImpl); + + void visitXmlElementChanged(final XmlElementChanged xmlElementChanged); + + void visitXmlTahChildAdd(final XmlTagChildAdd xmlTagChildAdd); + + void visitXmlTagChildChanged(final XmlTagChildChanged xmlTagChildChanged); + + void visitXmlTagChildRemoved(final XmlTagChildRemoved xmlTagChildRemoved); + + void visitXmlTagNameChanged(final XmlTagNameChanged xmlTagNameChanged); + + void visitXmlTextChanged(final XmlTextChanged xmlTextChanged); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlAttributeSet.java b/pom/src/com/intellij/pom/xml/events/XmlAttributeSet.java new file mode 100644 index 000000000000..512bfdf5bdec --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlAttributeSet.java @@ -0,0 +1,14 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.psi.xml.XmlTag; +import com.intellij.pom.xml.XmlChangeVisitor; + +public interface XmlAttributeSet extends XmlChange { + String getName(); + + String getValue(); + + XmlTag getTag(); + + void accept(XmlChangeVisitor visitor); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlChange.java b/pom/src/com/intellij/pom/xml/events/XmlChange.java new file mode 100644 index 000000000000..7057baa4d708 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlChange.java @@ -0,0 +1,8 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.pom.xml.XmlChangeVisitor; + + +public interface XmlChange { + void accept(XmlChangeVisitor visitor); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlDocumentChanged.java b/pom/src/com/intellij/pom/xml/events/XmlDocumentChanged.java new file mode 100644 index 000000000000..ed30eaf3828e --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlDocumentChanged.java @@ -0,0 +1,7 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.pom.xml.XmlChangeVisitor; + +public interface XmlDocumentChanged extends XmlChange { + void accept(XmlChangeVisitor visitor); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlElementChanged.java b/pom/src/com/intellij/pom/xml/events/XmlElementChanged.java new file mode 100644 index 000000000000..9d3b1cc58e97 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlElementChanged.java @@ -0,0 +1,10 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.psi.xml.XmlElement; +import com.intellij.pom.xml.XmlChangeVisitor; + +public interface XmlElementChanged extends XmlChange { + XmlElement getElement(); + + void accept(XmlChangeVisitor visitor); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlTagChildAdd.java b/pom/src/com/intellij/pom/xml/events/XmlTagChildAdd.java new file mode 100644 index 000000000000..5fa81b5309c1 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlTagChildAdd.java @@ -0,0 +1,13 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlTagChild; +import com.intellij.pom.xml.XmlChangeVisitor; + +public interface XmlTagChildAdd extends XmlChange { + XmlTag getTag(); + + XmlTagChild getChild(); + + void accept(XmlChangeVisitor visitor); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlTagChildChanged.java b/pom/src/com/intellij/pom/xml/events/XmlTagChildChanged.java new file mode 100644 index 000000000000..3821a93c6825 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlTagChildChanged.java @@ -0,0 +1,13 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlTagChild; +import com.intellij.pom.xml.XmlChangeVisitor; + +public interface XmlTagChildChanged extends XmlChange { + XmlTag getTag(); + + XmlTagChild getChild(); + + void accept(XmlChangeVisitor visitor); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlTagChildRemoved.java b/pom/src/com/intellij/pom/xml/events/XmlTagChildRemoved.java new file mode 100644 index 000000000000..5cd831f1db08 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlTagChildRemoved.java @@ -0,0 +1,13 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlTagChild; +import com.intellij.pom.xml.XmlChangeVisitor; + +public interface XmlTagChildRemoved extends XmlChange { + XmlTag getTag(); + + XmlTagChild getChild(); + + void accept(XmlChangeVisitor visitor); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlTagNameChanged.java b/pom/src/com/intellij/pom/xml/events/XmlTagNameChanged.java new file mode 100644 index 000000000000..729467802bb6 --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlTagNameChanged.java @@ -0,0 +1,12 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.psi.xml.XmlTag; +import com.intellij.pom.xml.XmlChangeVisitor; + +public interface XmlTagNameChanged extends XmlChange { + String getOldName(); + + XmlTag getTag(); + + void accept(XmlChangeVisitor visitor); +} diff --git a/pom/src/com/intellij/pom/xml/events/XmlTextChanged.java b/pom/src/com/intellij/pom/xml/events/XmlTextChanged.java new file mode 100644 index 000000000000..489ccca77ccb --- /dev/null +++ b/pom/src/com/intellij/pom/xml/events/XmlTextChanged.java @@ -0,0 +1,12 @@ +package com.intellij.pom.xml.impl.events; + +import com.intellij.pom.xml.XmlChangeVisitor; +import com.intellij.psi.xml.XmlText; + +public interface XmlTextChanged extends XmlChange { + String getOldText(); + + XmlText getText(); + + void accept(XmlChangeVisitor visitor); +} diff --git a/resources/src/componentSets/Core.xml b/resources/src/componentSets/Core.xml index 47e7b1a73312..b0f90de59c74 100644 --- a/resources/src/componentSets/Core.xml +++ b/resources/src/componentSets/Core.xml @@ -205,20 +205,20 @@ com.intellij.pom.core.impl.PomModelImpl - com.intellij.psi.impl.source.xml.XmlAspect - com.intellij.psi.impl.source.xml.XmlAspect + com.intellij.pom.xml.XmlAspect + com.intellij.pom.xml.impl.XmlAspectImpl com.intellij.pom.java.PomJavaAspect com.intellij.pom.java.impl.PomJavaAspectImpl - com.intellij.psi.impl.source.parsing.tabular.TreeAspect - com.intellij.psi.impl.source.parsing.tabular.TreeAspect + com.intellij.pom.tree.TreeAspect + com.intellij.pom.tree.TreeAspect - com.intellij.psi.impl.source.parsing.tabular.PsiEventWrapperAspect - com.intellij.psi.impl.source.parsing.tabular.PsiEventWrapperAspect + com.intellij.pom.wrappers.PsiEventWrapperAspect + com.intellij.pom.wrappers.PsiEventWrapperAspect com.intellij.psi.search.scope.packageSet.NamedScopeManager diff --git a/source/com/intellij/pom/tree/events/impl/ChangeInfoImpl.java b/source/com/intellij/pom/tree/events/impl/ChangeInfoImpl.java new file mode 100644 index 000000000000..f73741af3787 --- /dev/null +++ b/source/com/intellij/pom/tree/events/impl/ChangeInfoImpl.java @@ -0,0 +1,79 @@ +package com.intellij.pom.tree.events.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.impl.source.tree.SharedImplUtil; +import com.intellij.psi.impl.source.tree.TreeUtil; +import com.intellij.util.CharTable; +import com.intellij.pom.tree.events.ChangeInfo; +import com.intellij.pom.tree.events.TreeChange; + +public class ChangeInfoImpl implements ChangeInfo { + private static final String[] TO_STRING = {"add", "remove", "replace", "changed"}; + + public static ChangeInfoImpl create(short type, ASTNode changed, CharTable table){ + switch(type){ + case REPLACE: + return new ReplaceChangeInfoImpl(changed, table); + default: + return new ChangeInfoImpl(type, changed, table); + } + } + + private final short type; + private int myOldLength = 0; + + protected ChangeInfoImpl(short type, ASTNode changed, CharTable table){ + this.type = type; + myOldLength = TreeUtil.getNotCachedLength(changed, table); + } + + public int getChangeType(){ + return type; + } + + public String toString(){ + return TO_STRING[getChangeType()]; + } + + public void compactChange(ASTNode parent, TreeChange change){ + final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(parent); + final ASTNode[] affectedChildren = change.getAffectedChildren(); + for (int i = 0; i < affectedChildren.length; i++) { + final ASTNode treeElement = affectedChildren[i]; + final ChangeInfo changeByChild = change.getChangeByChild(treeElement); + processElementaryChange(changeByChild, treeElement, charTableByTree); + } + } + + public void processElementaryChange(ASTNode parent, final ChangeInfo changeByChild, final ASTNode treeElement) { + processElementaryChange(changeByChild, treeElement, SharedImplUtil.findCharTableByTree(parent)); + } + + private void processElementaryChange(final ChangeInfo changeByChild, final ASTNode treeElement, final CharTable charTableByTree) { + switch(changeByChild.getChangeType()){ + case ADD: + myOldLength -= TreeUtil.getNotCachedLength(treeElement, charTableByTree); + break; + case REMOVED: + myOldLength += changeByChild.getOldLength(); + break; + case REPLACE: + myOldLength -= TreeUtil.getNotCachedLength(treeElement, charTableByTree); + myOldLength += changeByChild.getOldLength(); + break; + case CONTENTS_CHANGED: + myOldLength -= TreeUtil.getNotCachedLength(treeElement, charTableByTree); + myOldLength += changeByChild.getOldLength(); + break; + } + } + + public int getOldLength(){ + return myOldLength; + } + + public void setOldLength(int oldTreeLength) { + myOldLength = oldTreeLength; + } + +} diff --git a/source/com/intellij/pom/tree/events/impl/ReplaceChangeInfoImpl.java b/source/com/intellij/pom/tree/events/impl/ReplaceChangeInfoImpl.java new file mode 100644 index 000000000000..763c09b1433d --- /dev/null +++ b/source/com/intellij/pom/tree/events/impl/ReplaceChangeInfoImpl.java @@ -0,0 +1,28 @@ +package com.intellij.pom.tree.events.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.impl.source.tree.SharedImplUtil; +import com.intellij.psi.impl.source.tree.TreeUtil; +import com.intellij.util.CharTable; +import com.intellij.pom.tree.events.ReplaceChangeInfo; + +public class ReplaceChangeInfoImpl extends ChangeInfoImpl implements ReplaceChangeInfo { + private ASTNode myReplaced; + private ASTNode myChanged; + + public ReplaceChangeInfoImpl(ASTNode changed, CharTable table) { + super(REPLACE, changed, table); + myChanged = changed; + } + + public ASTNode getReplaced(){ + return myReplaced; + } + + public void setReplaced(ASTNode replaced) { + CharTable charTableByTree = SharedImplUtil.findCharTableByTree(myChanged); + setOldLength(TreeUtil.getNotCachedLength(replaced, charTableByTree)); + myReplaced = replaced; + myReplaced.putUserData(CharTable.CHAR_TABLE_KEY, charTableByTree); + } +} diff --git a/source/com/intellij/pom/tree/events/impl/TreeChangeEventImpl.java b/source/com/intellij/pom/tree/events/impl/TreeChangeEventImpl.java new file mode 100644 index 000000000000..4cf92f556421 --- /dev/null +++ b/source/com/intellij/pom/tree/events/impl/TreeChangeEventImpl.java @@ -0,0 +1,173 @@ +package com.intellij.pom.tree.events.impl; + +import com.intellij.pom.PomModelAspect; +import com.intellij.psi.impl.source.tree.CompositeElement; +import com.intellij.psi.impl.source.tree.FileElement; +import com.intellij.psi.impl.source.tree.TreeElement; +import com.intellij.pom.tree.events.TreeChange; +import com.intellij.pom.tree.events.TreeChangeEvent; +import com.intellij.pom.tree.events.ChangeInfo; +import com.intellij.util.CharTable; +import com.intellij.lang.ASTNode; + +import java.util.*; + +/** + * Created by IntelliJ IDEA. + * User: ik + * Date: Oct 6, 2004 + * Time: 11:11:40 PM + * To change this template use File | Settings | File Templates. + */ +public class TreeChangeEventImpl implements TreeChangeEvent{ + private final Map myChangedElements = new HashMap(); + private final List> myOfEqualDepth = new ArrayList>(10); + private final PomModelAspect myAspect; + private final FileElement myFileElement; + + public TreeChangeEventImpl(PomModelAspect aspect, FileElement treeElement) { + myAspect = aspect; + myFileElement = treeElement; + } + + public FileElement getRootElement() { + return myFileElement; + } + + public TreeElement[] getChangedElements() { + final TreeElement[] ret = new TreeElement[myChangedElements.size()]; + final Iterator iterator = myChangedElements.keySet().iterator(); + int index = 0; + while (iterator.hasNext()) { + ret[index++] = (TreeElement)iterator.next(); + } + return ret; + } + + public TreeChange getChangesByElement(ASTNode element) { + return myChangedElements.get(element); + } + + public void addElementaryChange(ASTNode element, ChangeInfo change) { + int depth = 0; + final ASTNode parent = element.getTreeParent(); + if(parent == null) return; + ASTNode currentParent = parent; + ASTNode prevParent = element; + while(currentParent != null){ + if(myChangedElements.containsKey(currentParent)){ + final TreeChange changesByElement = getChangesByElement(currentParent); + final boolean currentParentHasChange = changesByElement.getChangeByChild(prevParent) != null; + if(currentParentHasChange && prevParent != element) return; + if(prevParent != element) change = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, prevParent, myFileElement.getCharTable()); + processElementaryChange(currentParent, prevParent, change, -1); + return; + } + depth++; + prevParent = currentParent; + currentParent = currentParent.getTreeParent(); + } + processElementaryChange(parent, element, change, depth - 1); + compactChanges(parent, depth - 1); + } + + private int getDepth(ASTNode element) { + int depth = 0; + while((element = element.getTreeParent()) != null) depth++; + return depth; + } + + public void clear() { + myChangedElements.clear(); + myOfEqualDepth.clear(); + } + + private void processElementaryChange(ASTNode parent, ASTNode element, ChangeInfo change, int depth) { + TreeChange treeChange = myChangedElements.get(parent); + if(treeChange == null){ + treeChange = new TreeChangeImpl(parent); + myChangedElements.put(parent, treeChange); + final int index = depth >= 0 ? depth : getDepth(parent); + Set treeElements = index < myOfEqualDepth.size() ? myOfEqualDepth.get(index) : null; + if(treeElements == null){ + treeElements = new HashSet(); + while(index > myOfEqualDepth.size()) + myOfEqualDepth.add(new HashSet()); + myOfEqualDepth.add(index, treeElements); + } + treeElements.add(parent); + } + treeChange.addChange(element, change); + if(change.getChangeType() == ChangeInfo.REMOVED){ + element.putUserData(CharTable.CHAR_TABLE_KEY, myFileElement.getCharTable()); + } + if(treeChange.isEmpty()) removeAssociatedChanges(parent, depth); + } + + private void compactChanges(ASTNode parent, int depth) { + int currentDepth = myOfEqualDepth.size(); + while(--currentDepth > depth){ + final Set treeElements = myOfEqualDepth.get(currentDepth); + if(treeElements == null) continue; + final Iterator iterator = treeElements.iterator(); + while (iterator.hasNext()) { + boolean isUnderCompacted = false; + final TreeElement treeElement = (TreeElement)iterator.next(); + ASTNode currentParent = treeElement; + while(currentParent != null){ + if(currentParent == parent){ + isUnderCompacted = true; + break; + } + currentParent = currentParent.getTreeParent(); + } + + if(isUnderCompacted){ + final ChangeInfoImpl compactedChange = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, treeElement, myFileElement.getCharTable()); + compactedChange.compactChange(treeElement, getChangesByElement(treeElement)); + + iterator.remove(); + myChangedElements.remove(treeElement); + final CompositeElement treeParent = treeElement.getTreeParent(); + final TreeChange changesByElement = getChangesByElement(treeParent); + if(changesByElement != null){ + final ChangeInfoImpl changeByChild = (ChangeInfoImpl)changesByElement.getChangeByChild(treeElement); + if(changeByChild != null){ + changeByChild.setOldLength(compactedChange.getOldLength()); + } + else{ + changesByElement.addChange(treeElement, compactedChange); + } + } + else processElementaryChange(treeParent, treeElement, compactedChange, currentDepth - 1); + } + } + } + } + + private void removeAssociatedChanges(ASTNode treeElement, int depth) { + if(myChangedElements.remove(treeElement) != null){ + if(depth < 0) depth = getDepth(treeElement); + if(depth < myOfEqualDepth.size()) + myOfEqualDepth.get(depth < 0 ? getDepth(treeElement) : depth).remove(treeElement); + } + } + + + public PomModelAspect getAspect() { + return myAspect; + } + + public String toString(){ + final StringBuffer buffer = new StringBuffer(); + final Iterator> iterator = myChangedElements.entrySet().iterator(); + while (iterator.hasNext()) { + final Map.Entry entry = iterator.next(); + buffer.append(entry.getKey().getElementType().toString()); + buffer.append(": "); + buffer.append(entry.getValue().toString()); + buffer.append("\n"); + } + return buffer.toString(); + } +} diff --git a/source/com/intellij/pom/tree/events/impl/TreeChangeImpl.java b/source/com/intellij/pom/tree/events/impl/TreeChangeImpl.java new file mode 100644 index 000000000000..017050f69cbd --- /dev/null +++ b/source/com/intellij/pom/tree/events/impl/TreeChangeImpl.java @@ -0,0 +1,138 @@ +package com.intellij.pom.tree.events.impl; + +import com.intellij.pom.tree.events.TreeChange; +import com.intellij.pom.tree.events.ChangeInfo; +import com.intellij.pom.tree.events.ReplaceChangeInfo; +import com.intellij.psi.impl.source.tree.*; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.lang.ASTNode; + +import java.util.*; + +public class TreeChangeImpl implements TreeChange { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.events.impl.TreeChangeImpl"); + private final Map myChanges = new LinkedHashMap(); + private final ASTNode myParent; + + public TreeChangeImpl(ASTNode parent) { + myParent = parent; + } + + public void addChange(ASTNode child, ChangeInfo changeInfo) { + LOG.assertTrue(child.getTreeParent() == myParent); + + final ChangeInfo current = myChanges.get(child); + + if(current != null && changeInfo.getChangeType() == ChangeInfo.CONTENTS_CHANGED){ + return; + } + + if(changeInfo.getChangeType() == ChangeInfo.REPLACE){ + final ReplaceChangeInfoImpl replaceChangeInfo = ((ReplaceChangeInfoImpl)changeInfo); + final ASTNode replaced = replaceChangeInfo.getReplaced(); + final ChangeInfo replacedInfo = myChanges.get(replaced); + + if(replacedInfo == null){ + //myChanges.put(replaced, ChangeInfo.create(ChangeInfo.REMOVED, replaced, SharedImplUtil.findCharTableByTree(myParent))); + myChanges.put(child, changeInfo); + } + else{ + switch(replacedInfo.getChangeType()){ + case ChangeInfo.REPLACE: + replaceChangeInfo.setOldLength(replacedInfo.getOldLength()); + replaceChangeInfo.setReplaced(((ReplaceChangeInfo)replacedInfo).getReplaced()); + break; + case ChangeInfo.ADD: + changeInfo = ChangeInfoImpl.create(ChangeInfo.ADD, replaced, SharedImplUtil.findCharTableByTree(myParent)); + myChanges.remove(replaced); + break; + } + myChanges.put(child, changeInfo); + } + return; + } + + if(current != null && current.getChangeType() == ChangeInfo.REMOVED){ + if(changeInfo.getChangeType() == ChangeInfo.ADD){ + myChanges.remove(child); + } + return; + } + + if(current != null && current.getChangeType() == ChangeInfo.ADD){ + if(changeInfo.getChangeType() == ChangeInfo.REMOVED){ + myChanges.remove(child); + } + return; + } + + if(changeInfo.getChangeType() == ChangeInfo.REMOVED){ + if(child instanceof LeafElement){ + final int charTabIndex = ((LeafElement)child).getCharTabIndex(); + if(checkLeaf(child.getTreeNext(), charTabIndex) || checkLeaf(child.getTreePrev(), charTabIndex)) return; + } + myChanges.put(child, changeInfo); + if(current != null) + ((ChangeInfoImpl)changeInfo).setOldLength(current.getOldLength()); + return; + } + + if(current == null){ + myChanges.put(child, changeInfo); + return; + } + } + + private boolean checkLeaf(final ASTNode treeNext, final int charTabIndex) { + if(!(treeNext instanceof LeafElement)) return false; + final ChangeInfo right = myChanges.get(treeNext); + if(right != null && right.getChangeType() == ChangeInfo.ADD){ + if(charTabIndex == ((LeafElement)treeNext).getCharTabIndex()){ + myChanges.remove(treeNext); + return true; + } + } + return false; + } + + public TreeElement[] getAffectedChildren() { + return myChanges.keySet().toArray(new TreeElement[myChanges.size()]); + } + + public ChangeInfo getChangeByChild(ASTNode child) { + return myChanges.get(child); + } + + public void composite(TreeChange treeChange) { + final TreeChangeImpl change = (TreeChangeImpl)treeChange; + final Set> entries = change.myChanges.entrySet(); + final Iterator> iterator = entries.iterator(); + while (iterator.hasNext()) { + final Map.Entry entry = iterator.next(); + addChange(entry.getKey(), entry.getValue()); + } + } + + public boolean isEmpty() { + return false; + } + + public void removeChange(ASTNode beforeEqualDepth) { + myChanges.remove(beforeEqualDepth); + } + + public String toString(){ + final StringBuffer buffer = new StringBuffer(); + final Iterator> iterator = myChanges.entrySet().iterator(); + while (iterator.hasNext()) { + final Map.Entry entry = iterator.next(); + buffer.append("("); + buffer.append(entry.getKey().getElementType().toString()); + buffer.append(", "); + buffer.append(entry.getValue().toString()); + buffer.append(")"); + if(iterator.hasNext()) buffer.append(", "); + } + return buffer.toString(); + } +} diff --git a/source/com/intellij/pom/wrappers/PsiEventWrapperAspect.java b/source/com/intellij/pom/wrappers/PsiEventWrapperAspect.java new file mode 100644 index 000000000000..42011cddc654 --- /dev/null +++ b/source/com/intellij/pom/wrappers/PsiEventWrapperAspect.java @@ -0,0 +1,133 @@ +package com.intellij.pom.wrappers; + +import com.intellij.lang.ASTNode; +import com.intellij.pom.PomModel; +import com.intellij.pom.PomModelAspect; +import com.intellij.pom.event.PomModelEvent; +import com.intellij.pom.tree.TreeAspect; +import com.intellij.pom.tree.events.ChangeInfo; +import com.intellij.pom.tree.events.ReplaceChangeInfo; +import com.intellij.pom.tree.events.TreeChange; +import com.intellij.pom.tree.events.TreeChangeEvent; +import com.intellij.pom.tree.events.impl.ChangeInfoImpl; +import com.intellij.pom.tree.events.impl.TreeChangeImpl; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.PsiManagerImpl; +import com.intellij.psi.impl.PsiTreeChangeEventImpl; +import com.intellij.psi.impl.source.SourceTreeToPsiMap; +import com.intellij.psi.impl.source.tree.FileElement; +import com.intellij.psi.impl.source.tree.TreeElement; + +import java.util.Collections; + +public class PsiEventWrapperAspect implements PomModelAspect{ + private final PomModel myModel; + private final TreeAspect myTreeAspect; + + public PsiEventWrapperAspect(PomModel model, TreeAspect aspect) { + myModel = model; + myTreeAspect = aspect; + myModel.registerAspect(this, Collections.singleton((PomModelAspect)aspect)); + } + + public void projectOpened() {} + public void projectClosed() {} + + public String getComponentName() { + return "PSI event wrapper aspect for POM"; + } + + public void initComponent() {} + public void disposeComponent() {} + public void update(PomModelEvent event) { + final TreeChangeEvent changeSet = (TreeChangeEvent)event.getChangeSet(myTreeAspect); + if(changeSet == null) return; + FileElement rootElement = (FileElement)changeSet.getRootElement(); + final PsiFile file = (PsiFile)SourceTreeToPsiMap.treeElementToPsi(rootElement); + final PsiManagerImpl manager = (PsiManagerImpl)file.getManager(); + if(manager == null) return; + + if(file.isPhysical()){ + final ASTNode[] changedElements = changeSet.getChangedElements(); + for (int i = 0; i < changedElements.length; i++) { + ASTNode changedElement = changedElements[i]; + TreeChange changesByElement = changeSet.getChangesByElement(changedElement); + PsiElement psiParent = null; + while(changedElement != null && (psiParent = SourceTreeToPsiMap.treeElementToPsi(changedElement)) == null){ + final ASTNode parent = changedElement.getTreeParent(); + final ChangeInfoImpl changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, changedElement, rootElement.getCharTable()); + changeInfo.compactChange(changedElement, changesByElement); + changesByElement = new TreeChangeImpl(parent); + changesByElement.addChange(changedElement, changeInfo); + changedElement = (TreeElement)parent; + } + if(changedElement == null) continue; + + final ASTNode[] affectedChildren = changesByElement.getAffectedChildren(); + boolean contentsChange = false; + for (int j = 0; j < affectedChildren.length; j++) { + if(changesByElement.getChangeByChild(affectedChildren[j]).getChangeType() == ChangeInfo.REMOVED){ + contentsChange = true; + break; + } + } + + if(contentsChange){ + final ChangeInfoImpl changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, changedElement, rootElement.getCharTable()); + changeInfo.compactChange(changedElement, changesByElement); + PsiTreeChangeEventImpl psiEvent = new PsiTreeChangeEventImpl(manager); + psiEvent.setParent(psiParent.getParent()); + psiEvent.setFile(file); + psiEvent.setChild(psiParent); + psiEvent.setOffset(changedElement.getStartOffset()); + psiEvent.setOldChild(psiParent); + psiEvent.setNewChild(psiParent); + psiEvent.setOldLength(changeInfo.getOldLength()); + //manager.beforeChildReplacement(psiEvent); + manager.childReplaced(psiEvent); + continue; + } + + for (int j = 0; j < affectedChildren.length; j++) { + final ASTNode treeElement = affectedChildren[j]; + PsiTreeChangeEventImpl psiEvent = new PsiTreeChangeEventImpl(manager); + psiEvent.setParent(psiParent); + psiEvent.setFile(file); + psiEvent.setChild(SourceTreeToPsiMap.treeElementToPsi(treeElement)); + + switch(changesByElement.getChangeByChild(treeElement).getChangeType()){ + case ChangeInfo.ADD: + psiEvent.setOffset(treeElement.getStartOffset()); + psiEvent.setOldLength(0); + //manager.beforeChildAddition(psiEvent); + manager.childAdded(psiEvent); + break; + case ChangeInfo.REPLACE: + final ReplaceChangeInfo changeByChild = (ReplaceChangeInfo)changesByElement.getChangeByChild(treeElement); + psiEvent.setOffset(treeElement.getStartOffset()); + final ASTNode replaced = changeByChild.getReplaced(); + psiEvent.setOldChild(SourceTreeToPsiMap.treeElementToPsi(replaced)); + psiEvent.setNewChild(SourceTreeToPsiMap.treeElementToPsi(treeElement)); + psiEvent.setOldLength(replaced.getTextLength()); + //manager.beforeChildReplacement(psiEvent); + manager.childReplaced(psiEvent); + break; + case ChangeInfo.CONTENTS_CHANGED: + final ChangeInfo contentsChangeInfo = changesByElement.getChangeByChild(treeElement); + psiEvent.setOffset(treeElement.getStartOffset()); + psiEvent.setOldChild(SourceTreeToPsiMap.treeElementToPsi(treeElement)); + psiEvent.setNewChild(SourceTreeToPsiMap.treeElementToPsi(treeElement)); + psiEvent.setOldLength(contentsChangeInfo.getOldLength()); + //manager.beforeChildReplacement(psiEvent); + manager.childReplaced(psiEvent); + break; + } + } + } + } + else{ + manager.nonPhysicalChange(); + } + } +} diff --git a/source/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java b/source/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java new file mode 100644 index 000000000000..2b8356d94567 --- /dev/null +++ b/source/com/intellij/pom/xml/impl/XmlAspectChangeSetImpl.java @@ -0,0 +1,58 @@ +package com.intellij.pom.xml.impl; + +import com.intellij.pom.PomModel; +import com.intellij.pom.PomModelAspect; +import com.intellij.pom.xml.XmlAspect; +import com.intellij.pom.xml.XmlChangeSet; +import com.intellij.pom.xml.impl.events.XmlChange; +import com.intellij.pom.event.PomChangeSet; +import com.intellij.pom.xml.impl.events.XmlChange; +import com.intellij.psi.xml.XmlFile; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class XmlAspectChangeSetImpl implements XmlChangeSet { + private final PomModel myModel; + private List myChanges = new ArrayList(); + private final XmlFile mySubjectToChange; + + public XmlAspectChangeSetImpl(PomModel model, XmlFile fileChanged) { + myModel = model; + mySubjectToChange = fileChanged; + } + + public XmlChange[] getChanges(){ + return myChanges.toArray(new XmlChange[myChanges.size()]); + } + + public PomModelAspect getAspect() { + return myModel.getModelAspect(XmlAspect.class); + } + + public void add(XmlChange xmlChange) { + myChanges.add(xmlChange); + } + + public void clear() { + myChanges.clear(); + } + + public XmlFile getChangedFile(){ + return mySubjectToChange; + } + + public String toString(){ + final StringBuffer buffer = new StringBuffer(); + final Iterator iterator = myChanges.iterator(); + while (iterator.hasNext()) { + XmlChange xmlChange = iterator.next(); + buffer.append("("); + buffer.append(xmlChange.toString()); + buffer.append(")"); + if(iterator.hasNext()) buffer.append(", "); + } + return buffer.toString(); + } +} diff --git a/source/com/intellij/pom/xml/impl/XmlAspectImpl.java b/source/com/intellij/pom/xml/impl/XmlAspectImpl.java new file mode 100644 index 000000000000..8ba3cda6c933 --- /dev/null +++ b/source/com/intellij/pom/xml/impl/XmlAspectImpl.java @@ -0,0 +1,186 @@ +package com.intellij.pom.xml.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.pom.PomModel; +import com.intellij.pom.PomModelAspect; +import com.intellij.pom.event.PomModelEvent; +import com.intellij.pom.tree.TreeAspect; +import com.intellij.pom.tree.events.ChangeInfo; +import com.intellij.pom.tree.events.ReplaceChangeInfo; +import com.intellij.pom.tree.events.TreeChange; +import com.intellij.pom.tree.events.TreeChangeEvent; +import com.intellij.pom.tree.events.impl.ChangeInfoImpl; +import com.intellij.pom.tree.events.impl.TreeChangeImpl; +import com.intellij.pom.xml.impl.events.*; +import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl; +import com.intellij.pom.xml.XmlAspect; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiReferenceExpression; +import com.intellij.psi.impl.source.SourceTreeToPsiMap; +import com.intellij.psi.impl.source.tree.FileElement; +import com.intellij.psi.impl.source.tree.TreeElement; +import com.intellij.psi.xml.*; +import com.intellij.util.CharTable; + +import java.util.Collections; + +public class XmlAspectImpl implements XmlAspect { + private final PomModel myModel; + private final TreeAspect myTreeAspect; + + public XmlAspectImpl(PomModel model, TreeAspect aspect) { + myModel = model; + myTreeAspect = aspect; + myModel.registerAspect(this, Collections.singleton((PomModelAspect)myTreeAspect)); + } + + public void update(PomModelEvent event) { + if (!event.getChangedAspects().contains(myTreeAspect)) return; + final TreeChangeEvent changeSet = (TreeChangeEvent)event.getChangeSet(myTreeAspect); + if (changeSet == null) return; + final ASTNode rootElement = changeSet.getRootElement(); + final PsiFile file = (PsiFile)rootElement.getPsi(); + if (!(file instanceof XmlFile)) return; + final XmlAspectChangeSetImpl xmlChangeSet = new XmlAspectChangeSetImpl(myModel, (XmlFile)file); + event.registerChangeSet(this, xmlChangeSet); + + final ASTNode[] changedElements = changeSet.getChangedElements(); + final CharTable table = ((FileElement)changeSet.getRootElement()).getCharTable(); + for (int i = 0; i < changedElements.length; i++) { + ASTNode changedElement = changedElements[i]; + TreeChange changesByElement = changeSet.getChangesByElement(changedElement); + PsiElement psiElement = null; + while (changedElement != null && (psiElement = SourceTreeToPsiMap.treeElementToPsi(changedElement)) == null) { + final ASTNode parent = changedElement.getTreeParent(); + final ChangeInfoImpl changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, changedElement, table); + changeInfo.compactChange(changedElement, changesByElement); + changesByElement = new TreeChangeImpl(parent); + changesByElement.addChange(changedElement, changeInfo); + changedElement = parent; + } + if (changedElement == null) continue; + final TreeChange finalChangedElement = changesByElement; + psiElement.accept(new PsiElementVisitor() { + TreeChange myChange = finalChangedElement; + + public void visitReferenceExpression(PsiReferenceExpression expression) { } + + public void visitElement(PsiElement element) { + final PsiElement parent = element.getParent(); + if (parent == null) return; + final ASTNode treeParent = SourceTreeToPsiMap.psiElementToTree(parent); + final ASTNode child = SourceTreeToPsiMap.psiElementToTree(element); + final ChangeInfoImpl changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, child, table); + + changeInfo.compactChange(child, myChange); + myChange = new TreeChangeImpl(treeParent); + + myChange.addChange(child, changeInfo); + parent.accept(this); + } + + public void visitXmlAttribute(XmlAttribute attribute) { + final ASTNode[] affectedChildren = myChange.getAffectedChildren(); + String oldName = null; + String oldValue = null; + for (int j = 0; j < affectedChildren.length; j++) { + final ASTNode treeElement = affectedChildren[j]; + final ChangeInfo changeByChild = myChange.getChangeByChild(treeElement); + final int changeType = changeByChild.getChangeType(); + if (treeElement.getElementType() == XmlTokenType.XML_NAME) { + if (changeType == ChangeInfo.REMOVED) { + oldName = ((TreeElement)treeElement).getText(table); + } + else if (changeType == ChangeInfo.REPLACE) { + oldName = ((TreeElement)((ReplaceChangeInfo)changeByChild).getReplaced()).getText(table); + } + } + if (treeElement.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) { + if (changeType == ChangeInfo.REMOVED) { + oldValue = ((TreeElement)treeElement).getText(table); + } + else if (changeType == ChangeInfo.REPLACE) { + oldValue = ((TreeElement)((ReplaceChangeInfo)changeByChild).getReplaced()).getText(table); + } + } + } + if (oldName != null && !oldName.equals(attribute.getName())) { + xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), oldName, null)); + xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), attribute.getName(), attribute.getValue())); + } + else if (oldValue != null) { + xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), attribute.getName(), attribute.getValue())); + } + else { + xmlChangeSet.add(new XmlElementChangedImpl(attribute)); + } + } + + public void visitXmlTag(XmlTag tag) { + ASTNode[] affectedChildren = shortenChange(myChange.getAffectedChildren(), changeSet); + + for (int j = 0; j < affectedChildren.length; j++) { + final ASTNode treeElement = affectedChildren[j]; + if (!(treeElement instanceof XmlTagChild)) { + visitElement(tag); + return; + } + } + + for (int j = 0; j < affectedChildren.length; j++) { + final ChangeInfo changeByChild = myChange.getChangeByChild(affectedChildren[j]); + final int changeType = changeByChild.getChangeType(); + final ASTNode treeElement = affectedChildren[j]; + switch (changeType) { + case ChangeInfo.ADD: + xmlChangeSet.add(new XmlTagChildAddImpl(tag, (XmlTagChild)treeElement)); + break; + case ChangeInfo.REMOVED: + treeElement.putUserData(CharTable.CHAR_TABLE_KEY, table); + xmlChangeSet.add(new XmlTagChildRemovedImpl(tag, (XmlTagChild)treeElement)); + break; + case ChangeInfo.CONTENTS_CHANGED: + xmlChangeSet.add(new XmlTagChildChangedImpl(tag, (XmlTagChild)treeElement)); + break; + case ChangeInfo.REPLACE: + final XmlTagChild replaced = (XmlTagChild)((ReplaceChangeInfo)changeByChild).getReplaced(); + replaced.putUserData(CharTable.CHAR_TABLE_KEY, table); + xmlChangeSet.add(new XmlTagChildRemovedImpl(tag, replaced)); + xmlChangeSet.add(new XmlTagChildAddImpl(tag, (XmlTagChild)treeElement)); + break; + } + } + } + + public void visitXmlDocument(XmlDocument document) { + xmlChangeSet.clear(); + xmlChangeSet.add(new XmlDocumentChangedImpl(document)); + } + + public void visitXmlFile(XmlFile file) { + xmlChangeSet.clear(); + xmlChangeSet.add(new XmlDocumentChangedImpl(file.getDocument())); + } + }); + } + } + + private ASTNode[] shortenChange(ASTNode[] affectedChildren, TreeChangeEvent event) { + // TODO + return affectedChildren; + } + + public void projectOpened() { } + + public void projectClosed() { } + + public void initComponent() { } + + public void disposeComponent() { } + + public String getComponentName() { + return "XML POM aspect"; + } +} diff --git a/source/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java b/source/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java index 6ef6532b587a..c1bc9f919e4c 100644 --- a/source/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java +++ b/source/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java @@ -1,26 +1,27 @@ package com.intellij.psi.impl.source.xml; +import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.TextRange; +import com.intellij.pom.PomModel; +import com.intellij.pom.xml.XmlAspect; +import com.intellij.pom.event.PomModelEvent; +import com.intellij.pom.impl.PomTransactionBase; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiReference; -import com.intellij.psi.tree.IElementType; -import com.intellij.psi.impl.source.tree.TreeElement; -import com.intellij.psi.impl.source.tree.*; -import com.intellij.psi.impl.source.xml.aspect.XmlAttributeSet; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; +import com.intellij.psi.impl.source.tree.ChildRole; +import com.intellij.psi.impl.source.tree.CompositeElement; +import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.meta.PsiMetaOwner; +import com.intellij.pom.xml.impl.events.XmlAttributeSetImpl; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.xml.*; import com.intellij.util.IncorrectOperationException; import com.intellij.xml.XmlAttributeDescriptor; import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.util.XmlUtil; -import com.intellij.pom.PomModel; -import com.intellij.pom.PomTransaction; -import com.intellij.pom.impl.PomTransactionBase; -import com.intellij.pom.event.PomModelEvent; -import com.intellij.lang.ASTNode; import java.util.ArrayList; import java.util.List; @@ -65,7 +66,7 @@ public class XmlAttributeImpl extends XmlElementImpl implements XmlAttribute { else { CodeEditUtil.addChild(XmlAttributeImpl.this, (TreeElement)newValue, null); } - return XmlAttributeSet.createXmlAttributeSet(model, getParent(), getName(), value != null ? value.getText() : null); + return XmlAttributeSetImpl.createXmlAttributeSet(model, getParent(), getName(), value != null ? value.getText() : null); } }, model.getModelAspect(XmlAspect.class)); } @@ -113,12 +114,12 @@ public class XmlAttributeImpl extends XmlElementImpl implements XmlAttribute { model.runTransaction(new PomTransactionBase(getParent()) { public PomModelEvent run(){ CodeEditUtil.replaceChild(XmlAttributeImpl.this, name, newName); - return XmlAttributeSet.createXmlAttributeSet(model, getParent(), nameText, getValue()); + return XmlAttributeSetImpl.createXmlAttributeSet(model, getParent(), nameText, getValue()); } }, model.getModelAspect(XmlAspect.class)); model.runTransaction(new PomTransactionBase(getParent()) { public PomModelEvent run(){ - return XmlAttributeSet.createXmlAttributeSet(model, getParent(), oldName, null); + return XmlAttributeSetImpl.createXmlAttributeSet(model, getParent(), oldName, null); } }, model.getModelAspect(XmlAspect.class)); diff --git a/source/com/intellij/psi/impl/source/xml/XmlDocumentImpl.java b/source/com/intellij/psi/impl/source/xml/XmlDocumentImpl.java index bbbbf96d851d..f917684e779c 100644 --- a/source/com/intellij/psi/impl/source/xml/XmlDocumentImpl.java +++ b/source/com/intellij/psi/impl/source/xml/XmlDocumentImpl.java @@ -2,6 +2,10 @@ package com.intellij.psi.impl.source.xml; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.pom.PomModel; +import com.intellij.pom.event.PomModelEvent; +import com.intellij.pom.impl.PomTransactionBase; +import com.intellij.pom.xml.XmlAspect; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiRecursiveElementVisitor; @@ -9,19 +13,15 @@ import com.intellij.psi.PsiReferenceExpression; import com.intellij.psi.impl.meta.MetaRegistry; import com.intellij.psi.impl.source.tree.ChildRole; import com.intellij.psi.impl.source.tree.TreeElement; -import com.intellij.psi.impl.source.xml.aspect.XmlDocumentChanged; import com.intellij.psi.meta.PsiMetaData; +import com.intellij.pom.xml.impl.events.XmlDocumentChangedImpl; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.CachedValue; import com.intellij.psi.xml.XmlDocument; import com.intellij.psi.xml.XmlProlog; import com.intellij.psi.xml.XmlTag; import com.intellij.psi.xml.XmlToken; -import com.intellij.xml.XmlNSDescriptor; -import com.intellij.pom.PomModel; -import com.intellij.pom.event.PomModelEvent; -import com.intellij.pom.impl.PomTransactionBase; import com.intellij.util.IncorrectOperationException; +import com.intellij.xml.XmlNSDescriptor; import gnu.trove.TObjectIntHashMap; /** @@ -30,8 +30,6 @@ import gnu.trove.TObjectIntHashMap; public class XmlDocumentImpl extends XmlElementImpl implements XmlDocument { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlDocumentImpl"); - private CachedValue myDescriptor = null; - public XmlDocumentImpl() { this(XML_DOCUMENT); } @@ -73,8 +71,6 @@ public class XmlDocumentImpl extends XmlElementImpl implements XmlDocument { public PsiElement copy() { final XmlDocumentImpl copy = (XmlDocumentImpl)super.copy(); - copy.myDescriptor = null; - return copy; } @@ -126,7 +122,7 @@ public class XmlDocumentImpl extends XmlElementImpl implements XmlDocument { model.runTransaction(new PomTransactionBase(this) { public PomModelEvent run() throws IncorrectOperationException { holder[0] = XmlDocumentImpl.super.addInternal(first, last, anchor, before); - return XmlDocumentChanged.createXmlDocumentChanged(model, XmlDocumentImpl.this); + return XmlDocumentChangedImpl.createXmlDocumentChanged(model, XmlDocumentImpl.this); } }, aspect); } @@ -141,7 +137,7 @@ public class XmlDocumentImpl extends XmlElementImpl implements XmlDocument { model.runTransaction(new PomTransactionBase(this) { public PomModelEvent run() throws IncorrectOperationException { XmlDocumentImpl.super.deleteChildInternal(child); - return XmlDocumentChanged.createXmlDocumentChanged(model, XmlDocumentImpl.this); + return XmlDocumentChangedImpl.createXmlDocumentChanged(model, XmlDocumentImpl.this); } }, aspect); } @@ -155,7 +151,7 @@ public class XmlDocumentImpl extends XmlElementImpl implements XmlDocument { model.runTransaction(new PomTransactionBase(this) { public PomModelEvent run() throws IncorrectOperationException { XmlDocumentImpl.super.replaceChildInternal(child, newElement); - return XmlDocumentChanged.createXmlDocumentChanged(model, XmlDocumentImpl.this); + return XmlDocumentChangedImpl.createXmlDocumentChanged(model, XmlDocumentImpl.this); } }, aspect); } diff --git a/source/com/intellij/psi/impl/source/xml/XmlTagImpl.java b/source/com/intellij/psi/impl/source/xml/XmlTagImpl.java index e47a1a32011f..deb2a9798725 100644 --- a/source/com/intellij/psi/impl/source/xml/XmlTagImpl.java +++ b/source/com/intellij/psi/impl/source/xml/XmlTagImpl.java @@ -9,9 +9,12 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.progress.ProgressManager; import com.intellij.pom.PomModel; +import com.intellij.pom.xml.XmlAspect; import com.intellij.pom.event.PomModelEvent; import com.intellij.pom.impl.PomTransactionBase; import com.intellij.psi.*; +import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl; +import com.intellij.pom.xml.impl.XmlAspectChangeSetImpl; import com.intellij.psi.impl.meta.MetaRegistry; import com.intellij.psi.impl.source.DummyHolder; import com.intellij.psi.impl.source.PsiFileImpl; @@ -22,7 +25,7 @@ import com.intellij.psi.impl.source.jsp.tagLibrary.TldUtil; import com.intellij.psi.impl.source.parsing.ParseUtil; import com.intellij.psi.impl.source.resolve.ResolveUtil; import com.intellij.psi.impl.source.tree.*; -import com.intellij.psi.impl.source.xml.aspect.*; +import com.intellij.pom.xml.impl.events.*; import com.intellij.psi.jsp.JspFile; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.search.PsiBaseElementProcessor; @@ -377,7 +380,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification final ASTNode childByRole = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(tag); if(childByRole != null) ChangeUtil.replaceChild(tag, (TreeElement)childByRole, ChangeUtil.copyElement((TreeElement)XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(dummyTag), charTableByTree)); - return XmlTagNameChanged.createXmlTagNameChanged(model, tag, oldName); + return XmlTagNameChangedImpl.createXmlTagNameChanged(model, tag, oldName); } }, model.getModelAspect(XmlAspect.class)); return this; @@ -750,7 +753,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification } retHolder[0] = treeElement; - return XmlAttributeSet.createXmlAttributeSet(model, XmlTagImpl.this, name, value); + return XmlAttributeSetImpl.createXmlAttributeSet(model, XmlTagImpl.this, name, value); } }, aspect); @@ -765,7 +768,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification public PomModelEvent run() { final TreeElement treeElement = addInternalHack(child, child, anchor, Boolean.valueOf(before), fileType); retHolder[0] = treeElement; - return XmlTagChildAdd.createXmlTagChildAdd(model, XmlTagImpl.this, (XmlTagChild)SourceTreeToPsiMap.treeElementToPsi(treeElement)); + return XmlTagChildAddImpl.createXmlTagChildAdd(model, XmlTagImpl.this, (XmlTagChild)SourceTreeToPsiMap.treeElementToPsi(treeElement)); } }, aspect); } @@ -773,8 +776,6 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification } public void deleteChildInternal(final ASTNode child) { - final PsiFile containingFile = getContainingFile(); - final FileType fileType = containingFile.getFileType(); final PomModel model = getProject().getModel(); final XmlAspect aspect = model.getModelAspect(XmlAspect.class); try { @@ -805,10 +806,10 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification } final PomModelEvent event = new PomModelEvent(model); { // event construction - final XmlAspectChangeSet xmlAspectChangeSet = new XmlAspectChangeSet(model, (XmlFile)getContainingFile()); - xmlAspectChangeSet.add(new XmlTagChildRemoved(XmlTagImpl.this, (XmlTagChild)treeNext)); - xmlAspectChangeSet.add(new XmlTagChildRemoved(XmlTagImpl.this, (XmlTagChild)child)); - xmlAspectChangeSet.add(new XmlTextChanged(xmlText, oldText)); + final XmlAspectChangeSetImpl xmlAspectChangeSet = new XmlAspectChangeSetImpl(model, (XmlFile)getContainingFile()); + xmlAspectChangeSet.add(new XmlTagChildRemovedImpl(XmlTagImpl.this, (XmlTagChild)treeNext)); + xmlAspectChangeSet.add(new XmlTagChildRemovedImpl(XmlTagImpl.this, (XmlTagChild)child)); + xmlAspectChangeSet.add(new XmlTextChangedImpl(xmlText, oldText)); event.registerChangeSet(model.getModelAspect(XmlAspect.class), xmlAspectChangeSet); } return event; @@ -824,10 +825,10 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification final String name = ((XmlAttribute)child).getName(); XmlTagImpl.super.deleteChildInternal(child); - return XmlAttributeSet.createXmlAttributeSet(model, XmlTagImpl.this, name, null); + return XmlAttributeSetImpl.createXmlAttributeSet(model, XmlTagImpl.this, name, null); } XmlTagImpl.super.deleteChildInternal(child); - return XmlTagChildRemoved.createXmlTagChildRemoved(model, XmlTagImpl.this, (XmlTagChild)SourceTreeToPsiMap.treeElementToPsi(child)); + return XmlTagChildRemovedImpl.createXmlTagChildRemoved(model, XmlTagImpl.this, (XmlTagChild)SourceTreeToPsiMap.treeElementToPsi(child)); } }, aspect); @@ -910,14 +911,14 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification final String text = xmlText.getText(); xmlText.insertText(xmlChildAsText.getValue(), xmlText.getValue().length()); myNewElement = left; - return XmlTextChanged.createXmlTextChanged(myModel, xmlText, text); + return XmlTextChangedImpl.createXmlTextChanged(myModel, xmlText, text); } if(right != null && right.getElementType() == XmlElementType.XML_TEXT){ final XmlText xmlText = (XmlText)right; final String text = xmlText.getText(); xmlText.insertText(xmlChildAsText.getValue(), 0); myNewElement = right; - return XmlTextChanged.createXmlTextChanged(myModel, xmlText, text); + return XmlTextChangedImpl.createXmlTextChanged(myModel, xmlText, text); } } @@ -952,7 +953,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification treeElement = addInternalHack(myChild, myChild, child, Boolean.FALSE, myFileType); } myNewElement = treeElement; - return XmlTagChildAdd.createXmlTagChildAdd(myModel, XmlTagImpl.this, (XmlTagChild)SourceTreeToPsiMap.treeElementToPsi(treeElement)); + return XmlTagChildAddImpl.createXmlTagChildAdd(myModel, XmlTagImpl.this, (XmlTagChild)SourceTreeToPsiMap.treeElementToPsi(treeElement)); } } } @@ -969,12 +970,12 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification // empty tag final XmlElement parent = getParent(); if(parent instanceof XmlTag) - return XmlTagChildChanged.createXmlTagChildChanged(myModel, (XmlTag)parent, XmlTagImpl.this); - return XmlDocumentChanged.createXmlDocumentChanged(myModel, (XmlDocument)parent); + return XmlTagChildChangedImpl.createXmlTagChildChanged(myModel, (XmlTag)parent, XmlTagImpl.this); + return XmlDocumentChangedImpl.createXmlDocumentChanged(myModel, (XmlDocument)parent); } } myNewElement = treeElement; - return XmlTagChildAdd.createXmlTagChildAdd(myModel, XmlTagImpl.this, (XmlTagChild)SourceTreeToPsiMap.treeElementToPsi(treeElement)); + return XmlTagChildAddImpl.createXmlTagChildAdd(myModel, XmlTagImpl.this, (XmlTagChild)SourceTreeToPsiMap.treeElementToPsi(treeElement)); } TreeElement getNewElement(){ @@ -1033,9 +1034,9 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag/*, Modification final PomModelEvent event = new PomModelEvent(model); {// event construction - final XmlAspectChangeSet change = new XmlAspectChangeSet(model, (XmlFile)(containingFile instanceof XmlFile ? containingFile : null)); - change.add(new XmlTextChanged(childText, text)); - change.add(new XmlTagChildAdd(XmlTagImpl.this, rightText)); + final XmlAspectChangeSetImpl change = new XmlAspectChangeSetImpl(model, (XmlFile)(containingFile instanceof XmlFile ? containingFile : null)); + change.add(new XmlTextChangedImpl(childText, text)); + change.add(new XmlTagChildAddImpl(XmlTagImpl.this, rightText)); event.registerChangeSet(aspect, change); } myRight = rightText; diff --git a/source/com/intellij/psi/impl/source/xml/XmlTextImpl.java b/source/com/intellij/psi/impl/source/xml/XmlTextImpl.java index 1e600d440e88..529afc12bbb5 100644 --- a/source/com/intellij/psi/impl/source/xml/XmlTextImpl.java +++ b/source/com/intellij/psi/impl/source/xml/XmlTextImpl.java @@ -4,12 +4,13 @@ import com.intellij.lang.ASTNode; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.diagnostic.Logger; import com.intellij.pom.PomModel; +import com.intellij.pom.xml.XmlAspect; import com.intellij.pom.event.PomModelEvent; import com.intellij.pom.impl.PomTransactionBase; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.impl.source.tree.TreeElement; -import com.intellij.psi.impl.source.xml.aspect.XmlTextChanged; +import com.intellij.pom.xml.impl.events.XmlTextChangedImpl; import com.intellij.psi.tree.IElementType; import com.intellij.psi.xml.*; import com.intellij.util.IncorrectOperationException; @@ -159,7 +160,7 @@ public class XmlTextImpl extends XmlElementImpl implements XmlText { final String oldText = getText(); replaceAllChildrenToChildrenOf(firstEncodedElement.getTreeParent()); clearCaches(); - return XmlTextChanged.createXmlTextChanged(model, XmlTextImpl.this, oldText); + return XmlTextChangedImpl.createXmlTextChanged(model, XmlTextImpl.this, oldText); } }, aspect); }