mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Draft PsiBuilder implementation.
This commit is contained in:
@@ -4,6 +4,7 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.util.Key;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
@@ -16,27 +17,46 @@ public interface ASTNode extends UserDataHolder {
|
||||
IElementType getElementType();
|
||||
|
||||
String getText();
|
||||
|
||||
boolean textContains(char c);
|
||||
|
||||
int getStartOffset();
|
||||
|
||||
int getTextLength();
|
||||
|
||||
TextRange getTextRange();
|
||||
|
||||
ASTNode getTreeParent();
|
||||
|
||||
ASTNode getFirstChildNode();
|
||||
|
||||
ASTNode getLastChildNode();
|
||||
|
||||
ASTNode getTreeNext();
|
||||
|
||||
ASTNode getTreePrev();
|
||||
|
||||
ASTNode[] getChildren(TokenSet filter);
|
||||
|
||||
void addChild(ASTNode child);
|
||||
|
||||
void addChild(ASTNode child, ASTNode anchorBefore);
|
||||
|
||||
void removeChild(ASTNode child);
|
||||
|
||||
void replaceChild(ASTNode oldChild, ASTNode newChild);
|
||||
|
||||
void replaceAllChildrenToChildrenOf(ASTNode anotherParent);
|
||||
|
||||
void addChildren(ASTNode firstChild, ASTNode lastChild, ASTNode anchorBefore);
|
||||
|
||||
Object clone();
|
||||
|
||||
ASTNode copyElement();
|
||||
|
||||
ASTNode findLeafElementAt(int offset);
|
||||
|
||||
<T> T getCopyableUserData(Key<T> key);
|
||||
|
||||
<T> void putCopyableUserData(Key<T> key, T value);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import com.intellij.psi.tree.IElementType;
|
||||
*/
|
||||
public interface ParserDefinition {
|
||||
Lexer createLexer();
|
||||
|
||||
PsiParser createParser();
|
||||
|
||||
PsiElement createElement(ASTNode node);
|
||||
}
|
||||
|
||||
@@ -11,13 +11,30 @@ import com.intellij.psi.PsiElement;
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public interface PsiBuilder {
|
||||
interface Marker {}
|
||||
interface Marker {
|
||||
}
|
||||
|
||||
interface Lexem {
|
||||
IElementType getTokenType();
|
||||
|
||||
String getTokenText();
|
||||
}
|
||||
|
||||
void advanceLexer();
|
||||
|
||||
Lexem getCurrentLexem();
|
||||
|
||||
Marker start(IElementType symbol);
|
||||
|
||||
void rollbackTo(Marker marker);
|
||||
|
||||
void drop(Marker marker);
|
||||
|
||||
void done(Marker marker);
|
||||
|
||||
void insertErrorElement(String messageText);
|
||||
|
||||
PsiElement getTreeBuilt();
|
||||
boolean eof();
|
||||
|
||||
ASTNode getTreeBuilt();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.intellij.lang;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.lexer.Lexer;
|
||||
|
||||
/**
|
||||
@@ -11,5 +12,5 @@ import com.intellij.lexer.Lexer;
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public interface PsiParser {
|
||||
PsiElement parse(Lexer lexer, PsiBuilder builder);
|
||||
PsiElement parse(IElementType root, Lexer lexer, PsiBuilder builder);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
package com.intellij.lang.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.CharTable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: max
|
||||
* Date: Jan 21, 2005
|
||||
* Time: 3:30:29 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class PsiBuilderImpl implements PsiBuilder {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.lang.impl.PsiBuilderImpl");
|
||||
|
||||
private List<Lexem> myLexems = new ArrayList<Lexem>();
|
||||
private List<Object> myProduction = new ArrayList<Object>();
|
||||
|
||||
private Lexer myLexer;
|
||||
private int myCurrentLexem;
|
||||
private CharTable myCharTable;
|
||||
private boolean myStarted = false;
|
||||
|
||||
public PsiBuilderImpl(final Lexer lexer, final CharTable charTable) {
|
||||
myCharTable = charTable;
|
||||
myLexer = lexer;
|
||||
}
|
||||
|
||||
private static class MarkerImpl implements Marker {
|
||||
public IElementType myType;
|
||||
public int myLexemIndex;
|
||||
public DoneMarker myDoneMarker = null;
|
||||
|
||||
public MarkerImpl(final IElementType type, int idx) {
|
||||
myType = type;
|
||||
myLexemIndex = idx;
|
||||
}
|
||||
}
|
||||
|
||||
private class LexemImpl implements Lexem {
|
||||
private IElementType myTokenType;
|
||||
private int myTokenStart;
|
||||
private int myTokenEnd;
|
||||
private int myState;
|
||||
|
||||
public LexemImpl() {
|
||||
myTokenType = myLexer.getTokenType();
|
||||
myTokenStart = myLexer.getTokenStart();
|
||||
myTokenEnd = myLexer.getTokenEnd();
|
||||
myState = myLexer.getState();
|
||||
}
|
||||
|
||||
public IElementType getTokenType() {
|
||||
return myTokenType;
|
||||
}
|
||||
|
||||
public String getTokenText() {
|
||||
return new String(myLexer.getBuffer(), myTokenStart, myTokenEnd - myTokenStart);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DoneMarker {
|
||||
public MarkerImpl myMarker;
|
||||
|
||||
public DoneMarker(final MarkerImpl marker) {
|
||||
myMarker = marker;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ErrorItem {
|
||||
String myMessage;
|
||||
|
||||
public ErrorItem(final String message) {
|
||||
myMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
public void advanceLexer() {
|
||||
myProduction.add(getCurrentLexem());
|
||||
myCurrentLexem++;
|
||||
if (myCurrentLexem > myLexems.size()) {
|
||||
LOG.assertTrue(!eof());
|
||||
final Lexem lxm = advanceOriginalLexer();
|
||||
if (lxm == null) return;
|
||||
myLexems.add(lxm);
|
||||
}
|
||||
}
|
||||
|
||||
private Lexem advanceOriginalLexer() {
|
||||
myLexer.advance();
|
||||
return myLexer.getTokenType() == null ? null : new LexemImpl();
|
||||
}
|
||||
|
||||
|
||||
public Lexem getCurrentLexem() {
|
||||
return myLexems.get(myCurrentLexem);
|
||||
}
|
||||
|
||||
public Marker start(IElementType symbol) {
|
||||
if (!myStarted) {
|
||||
myStarted = true;
|
||||
myLexems.add(new LexemImpl());
|
||||
}
|
||||
|
||||
MarkerImpl marker = new MarkerImpl(symbol, myCurrentLexem);
|
||||
myProduction.add(marker);
|
||||
return marker;
|
||||
}
|
||||
|
||||
public boolean eof() {
|
||||
if (myCurrentLexem + 1 < myLexems.size()) return false;
|
||||
if (myLexer.getTokenType() == null) return true;
|
||||
final Lexem lxm = advanceOriginalLexer();
|
||||
if (lxm == null) return true;
|
||||
myLexems.add(lxm);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void rollbackTo(Marker marker) {
|
||||
myCurrentLexem = ((MarkerImpl)marker).myLexemIndex;
|
||||
int idx = myProduction.lastIndexOf(marker);
|
||||
|
||||
LOG.assertTrue(idx >= 0, "The marker must be added before rolled back to.");
|
||||
for (int i = myProduction.size() - 1; i >= idx; i--) {
|
||||
myProduction.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void drop(Marker marker) {
|
||||
final boolean removed = myProduction.remove(marker);
|
||||
LOG.assertTrue(removed, "The marker must be added before it is dropped.");
|
||||
}
|
||||
|
||||
public void done(Marker marker) {
|
||||
LOG.assertTrue(((MarkerImpl)marker).myDoneMarker == null, "Marker already done.");
|
||||
int idx = myProduction.lastIndexOf(marker);
|
||||
LOG.assertTrue(idx >= 0, "Marker never been added.");
|
||||
|
||||
for (int i = myProduction.size() - 1; i > idx; i--) {
|
||||
Object item = myProduction.get(i);
|
||||
if (item instanceof Marker) {
|
||||
MarkerImpl otherMarker = (MarkerImpl)item;
|
||||
if (otherMarker.myDoneMarker == null) {
|
||||
LOG.error("Another not done marker of type [" + otherMarker.myType + "] added after this one. Must be done before this.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoneMarker doneMarker = new DoneMarker((MarkerImpl)marker);
|
||||
((MarkerImpl)marker).myDoneMarker = doneMarker;
|
||||
myProduction.add(doneMarker);
|
||||
}
|
||||
|
||||
public void insertErrorElement(String messageText) {
|
||||
myProduction.add(new ErrorItem(messageText));
|
||||
}
|
||||
|
||||
public ASTNode getTreeBuilt() {
|
||||
MarkerImpl rootMarker = (MarkerImpl)myProduction.get(0);
|
||||
ASTNode rootNode = new CompositeElement(rootMarker.myType);
|
||||
rootNode.putUserData(CharTable.CHAR_TABLE_KEY, myCharTable);
|
||||
|
||||
ASTNode curNode = rootNode;
|
||||
for (int i = 1; i < myProduction.size(); i++) {
|
||||
LOG.assertTrue(curNode != null, "Unexpected end of the production");
|
||||
Object item = myProduction.get(i);
|
||||
if (item instanceof LexemImpl) {
|
||||
LexemImpl lexem = (LexemImpl)item;
|
||||
final LeafPsiElement childNode = new LeafPsiElement(lexem.getTokenType(),
|
||||
myLexer.getBuffer(),
|
||||
lexem.myTokenStart,
|
||||
lexem.myTokenEnd,
|
||||
lexem.myState,
|
||||
myCharTable);
|
||||
TreeUtil.addChildren((CompositeElement)curNode, childNode);
|
||||
}
|
||||
else if (item instanceof MarkerImpl) {
|
||||
MarkerImpl marker = (MarkerImpl)item;
|
||||
ASTNode childNode = new CompositeElement(marker.myType);
|
||||
TreeUtil.addChildren((CompositeElement)curNode, (TreeElement)childNode);
|
||||
curNode = childNode;
|
||||
}
|
||||
else if (item instanceof DoneMarker) {
|
||||
DoneMarker doneMarker = (DoneMarker)item;
|
||||
LOG.assertTrue(doneMarker.myMarker.myType == curNode.getElementType());
|
||||
curNode = curNode.getTreeParent();
|
||||
}
|
||||
else if (item instanceof ErrorItem) {
|
||||
final PsiErrorElementImpl errorElement = new PsiErrorElementImpl();
|
||||
errorElement.setErrorDescription(((ErrorItem)item).myMessage);
|
||||
TreeUtil.addChildren((CompositeElement)curNode, errorElement);
|
||||
}
|
||||
}
|
||||
|
||||
LOG.assertTrue(curNode == null, "Unbalanced tree");
|
||||
|
||||
return rootNode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
package com.intellij.psi.impl.source;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.impl.ElementBase;
|
||||
import com.intellij.psi.impl.SharedPsiElementImplUtil;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.FileStatusManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.ide.util.EditSourceUtil;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: max
|
||||
* Date: Jan 20, 2005
|
||||
* Time: 2:54:30 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class ASTWrapperPsiElement extends ElementBase implements PsiElement, NavigationItem {
|
||||
private ASTNode myNode;
|
||||
|
||||
public ASTWrapperPsiElement(final ASTNode node) {
|
||||
myNode = node;
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
final PsiManager manager = getManager();
|
||||
return manager != null ? manager.getProject() : null;
|
||||
}
|
||||
|
||||
public PsiManager getManager() {
|
||||
return getParent().getManager();
|
||||
}
|
||||
|
||||
public PsiElement[] getChildren() {
|
||||
return new PsiElement[0];
|
||||
}
|
||||
|
||||
public PsiElement getParent() {
|
||||
return SourceTreeToPsiMap.treeElementToPsi(myNode.getTreeParent());
|
||||
}
|
||||
|
||||
public PsiElement getFirstChild() {
|
||||
return SourceTreeToPsiMap.treeElementToPsi(myNode.getFirstChildNode());
|
||||
}
|
||||
|
||||
public PsiElement getLastChild() {
|
||||
return SourceTreeToPsiMap.treeElementToPsi(myNode.getLastChildNode());
|
||||
}
|
||||
|
||||
public PsiElement getNextSibling() {
|
||||
return SourceTreeToPsiMap.treeElementToPsi(myNode.getTreeNext());
|
||||
}
|
||||
|
||||
public PsiElement getPrevSibling() {
|
||||
return SourceTreeToPsiMap.treeElementToPsi(myNode.getTreePrev());
|
||||
}
|
||||
|
||||
public PsiFile getContainingFile() {
|
||||
return getParent().getContainingFile();
|
||||
}
|
||||
|
||||
public TextRange getTextRange() {
|
||||
return myNode.getTextRange();
|
||||
}
|
||||
|
||||
public int getStartOffsetInParent() {
|
||||
return myNode.getStartOffset() - myNode.getTreeParent().getStartOffset();
|
||||
}
|
||||
|
||||
public int getTextLength() {
|
||||
return myNode.getTextLength();
|
||||
}
|
||||
|
||||
public PsiElement findElementAt(int offset) {
|
||||
ASTNode treeElement = myNode.findLeafElementAt(offset);
|
||||
return SourceTreeToPsiMap.treeElementToPsi(treeElement);
|
||||
}
|
||||
|
||||
public PsiReference findReferenceAt(int offset) {
|
||||
return SharedPsiElementImplUtil.findReferenceAt(this, offset);
|
||||
}
|
||||
|
||||
public int getTextOffset() {
|
||||
return myNode.getStartOffset();
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return myNode.getText();
|
||||
}
|
||||
|
||||
public char[] textToCharArray() {
|
||||
return myNode.getText().toCharArray();
|
||||
}
|
||||
|
||||
public PsiElement getNavigationElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public PsiElement getOriginalElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
//Q: get rid of these methods?
|
||||
public boolean textMatches(CharSequence text) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean textMatches(PsiElement element) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean textContains(char c) {
|
||||
return myNode.textContains(c);
|
||||
}
|
||||
|
||||
public void accept(PsiElementVisitor visitor) {
|
||||
visitor.visitElement(this);
|
||||
}
|
||||
|
||||
public void acceptChildren(PsiElementVisitor visitor) {
|
||||
ASTNode child = myNode.getFirstChildNode();
|
||||
while (child != null) {
|
||||
SourceTreeToPsiMap.treeElementToPsi(child).accept(visitor);
|
||||
child = child.getTreeNext();
|
||||
}
|
||||
}
|
||||
|
||||
public PsiElement copy() {
|
||||
return (PsiElement)clone();
|
||||
}
|
||||
|
||||
public PsiElement add(PsiElement element) throws IncorrectOperationException {
|
||||
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public PsiElement addBefore(PsiElement element, PsiElement anchor) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public PsiElement addAfter(PsiElement element, PsiElement anchor) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void checkAdd(PsiElement element) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public PsiElement addRangeBefore(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void delete() throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void checkDelete() throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void deleteChildRange(PsiElement first, PsiElement last) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public PsiElement replace(PsiElement newElement) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return getManager() != null;
|
||||
}
|
||||
|
||||
public boolean isWritable() {
|
||||
return getContainingFile().isWritable();
|
||||
}
|
||||
|
||||
public PsiReference getReference() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public PsiReference[] getReferences() {
|
||||
return SharedPsiElementImplUtil.getReferences(this);
|
||||
}
|
||||
|
||||
public boolean processDeclarations(PsiScopeProcessor processor,
|
||||
PsiSubstitutor substitutor,
|
||||
PsiElement lastParent,
|
||||
PsiElement place) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public PsiElement getContext() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean isPhysical() {
|
||||
return getContainingFile().isPhysical();
|
||||
}
|
||||
|
||||
public GlobalSearchScope getResolveScope() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public GlobalSearchScope getUseScope() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ItemPresentation getPresentation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void navigate(boolean requestFocus) {
|
||||
if (canNavigate()) {
|
||||
EditSourceUtil.getDescriptor(getNavigationElement()).navigate(requestFocus);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canNavigate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public FileStatus getFileStatus() {
|
||||
if (!isPhysical()) return FileStatus.NOT_CHANGED;
|
||||
PsiFile contFile = getContainingFile();
|
||||
if (contFile == null) return FileStatus.NOT_CHANGED;
|
||||
VirtualFile vFile = contFile.getVirtualFile();
|
||||
return vFile != null ? FileStatusManager.getInstance(getProject()).getStatus(vFile) : FileStatus.NOT_CHANGED;
|
||||
}
|
||||
|
||||
public <T> T getCopyableUserData(Key<T> key) {
|
||||
return myNode.getCopyableUserData(key);
|
||||
}
|
||||
|
||||
public <T> void putCopyableUserData(Key<T> key, T value) {
|
||||
myNode.putCopyableUserData(key, value);
|
||||
}
|
||||
|
||||
public ASTNode getNode() {
|
||||
return myNode;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,9 @@ public class SourceTreeToPsiMap {
|
||||
return RepositoryElementsManager.getOrFindPsiElement((RepositoryTreeElement)element);
|
||||
}
|
||||
else {
|
||||
PsiElement psiElement = element.getUserData(TreeElement.PSI_ELEMENT_KEY);
|
||||
if (psiElement != null) return psiElement;
|
||||
|
||||
LOG.error("Not PsiElement:" + element);
|
||||
return null;
|
||||
}
|
||||
@@ -39,6 +42,9 @@ public class SourceTreeToPsiMap {
|
||||
else if (psiElement instanceof SrcRepositoryPsiElement) {
|
||||
return RepositoryElementsManager.getOrFindTreeElement((SrcRepositoryPsiElement)psiElement);
|
||||
}
|
||||
else if (psiElement instanceof ASTWrapperPsiElement) {
|
||||
return ((ASTWrapperPsiElement)psiElement).getNode();
|
||||
}
|
||||
else {
|
||||
LOG.error("Not TreeElement:" + psiElement);
|
||||
return null;
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.CharTable;
|
||||
import com.intellij.lang.ASTNode;
|
||||
|
||||
public class CompositeElement extends TreeElement implements Cloneable{
|
||||
public class CompositeElement extends TreeElement implements Cloneable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.CompositeElement");
|
||||
|
||||
public TreeElement prev = null;
|
||||
@@ -30,51 +30,56 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getModificationCount(){
|
||||
public int getModificationCount() {
|
||||
return myModificationsCount;
|
||||
}
|
||||
|
||||
public int getStartOffset() {
|
||||
CompositeElement parent = this;
|
||||
int sum = 0;
|
||||
while(parent != null){
|
||||
while (parent != null) {
|
||||
sum += parent.getModificationCount();
|
||||
parent = parent.getTreeParent();
|
||||
}
|
||||
if(sum != myParentModifications){
|
||||
if (sum != myParentModifications) {
|
||||
myParentModifications = sum;
|
||||
if(prev != null) myStartOffset = prev.getStartOffset() + prev.getTextLength();
|
||||
if (prev != null) {
|
||||
myStartOffset = prev.getStartOffset() + prev.getTextLength();
|
||||
}
|
||||
else {
|
||||
if(this.parent != null)
|
||||
if (this.parent != null) {
|
||||
myStartOffset = this.parent.getStartOffset();
|
||||
else myStartOffset = 0;
|
||||
}
|
||||
else {
|
||||
myStartOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return myStartOffset;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
CompositeElement clone = (CompositeElement)super.clone();
|
||||
CompositeElement clone = (CompositeElement)super.clone();
|
||||
|
||||
synchronized (PsiLock.LOCK) {
|
||||
clone.clearCaches();
|
||||
clone.parent = null;
|
||||
clone.prev = null;
|
||||
clone.firstChild = null;
|
||||
clone.lastChild = null;
|
||||
clone.myModificationsCount = 0;
|
||||
clone.myParentModifications = -1;
|
||||
for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
TreeUtil.addChildren(clone, (TreeElement)child.clone());
|
||||
}
|
||||
synchronized (PsiLock.LOCK) {
|
||||
clone.clearCaches();
|
||||
clone.parent = null;
|
||||
clone.prev = null;
|
||||
clone.firstChild = null;
|
||||
clone.lastChild = null;
|
||||
clone.myModificationsCount = 0;
|
||||
clone.myParentModifications = -1;
|
||||
for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
TreeUtil.addChildren(clone, (TreeElement)child.clone());
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
public void subtreeChanged() {
|
||||
clearCaches();
|
||||
CompositeElement treeParent = getTreeParent();
|
||||
if(treeParent != null) treeParent.subtreeChanged();
|
||||
if (treeParent != null) treeParent.subtreeChanged();
|
||||
}
|
||||
|
||||
public void clearCaches() {
|
||||
@@ -108,23 +113,23 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
|
||||
public LeafElement findLeafElementAt(int offset) {
|
||||
|
||||
synchronized (PsiLock.LOCK) {
|
||||
final CharTable table = SharedImplUtil.findCharTableByTree(this);
|
||||
TreeElement child = firstChild;
|
||||
while (child != null) {
|
||||
final int textLength = child.getTextLength(table);
|
||||
if (textLength > offset) {
|
||||
if (child instanceof ChameleonElement) {
|
||||
child = ChameleonTransforming.transform((ChameleonElement)child);
|
||||
continue;
|
||||
}
|
||||
return child.findLeafElementAt(offset);
|
||||
synchronized (PsiLock.LOCK) {
|
||||
final CharTable table = SharedImplUtil.findCharTableByTree(this);
|
||||
TreeElement child = firstChild;
|
||||
while (child != null) {
|
||||
final int textLength = child.getTextLength(table);
|
||||
if (textLength > offset) {
|
||||
if (child instanceof ChameleonElement) {
|
||||
child = ChameleonTransforming.transform((ChameleonElement)child);
|
||||
continue;
|
||||
}
|
||||
offset -= textLength;
|
||||
child = child.getTreeNext();
|
||||
return child.findLeafElementAt(offset);
|
||||
}
|
||||
return null;
|
||||
offset -= textLength;
|
||||
child = child.getTreeNext();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
@@ -132,21 +137,21 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
}
|
||||
|
||||
public String getText(CharTable table) {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
// check if all elements are laid out consequently in the same buffer (optimization):
|
||||
char[] buffer = new char[getTextLength()];
|
||||
SourceUtil.toBuffer(this, buffer, 0, table);
|
||||
//return StringFactory.createStringFromConstantArray(buffer);
|
||||
return new String(buffer);
|
||||
}
|
||||
synchronized (PsiLock.LOCK) {
|
||||
// check if all elements are laid out consequently in the same buffer (optimization):
|
||||
char[] buffer = new char[getTextLength()];
|
||||
SourceUtil.toBuffer(this, buffer, 0, table);
|
||||
//return StringFactory.createStringFromConstantArray(buffer);
|
||||
return new String(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public char[] textToCharArray() {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
char[] buffer = new char[getTextLength()];
|
||||
SourceUtil.toBuffer(this, buffer, 0);
|
||||
return buffer;
|
||||
}
|
||||
synchronized (PsiLock.LOCK) {
|
||||
char[] buffer = new char[getTextLength()];
|
||||
SourceUtil.toBuffer(this, buffer, 0);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean textContains(char c) {
|
||||
@@ -160,13 +165,13 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
}
|
||||
|
||||
public ASTNode findChildByRole(int role) {
|
||||
LOG.assertTrue(ChildRole.isUnique(role));
|
||||
synchronized (PsiLock.LOCK) {
|
||||
for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
if (getChildRole(child) == role) return child;
|
||||
}
|
||||
LOG.assertTrue(ChildRole.isUnique(role));
|
||||
synchronized (PsiLock.LOCK) {
|
||||
for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
if (getChildRole(child) == role) return child;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getChildRole(ASTNode child) {
|
||||
@@ -175,10 +180,10 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
}
|
||||
|
||||
protected final int getChildRole(ASTNode child, int roleCandidate) {
|
||||
if (findChildByRole(roleCandidate) == child){
|
||||
if (findChildByRole(roleCandidate) == child) {
|
||||
return roleCandidate;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
return ChildRole.NONE;
|
||||
}
|
||||
}
|
||||
@@ -190,8 +195,8 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
}
|
||||
final ASTNode[] result = new ASTNode[count];
|
||||
count = 0;
|
||||
for(ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()){
|
||||
if (filter == null || filter.isInSet(child.getElementType())){
|
||||
for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
if (filter == null || filter.isInSet(child.getElementType())) {
|
||||
result[count++] = child;
|
||||
}
|
||||
}
|
||||
@@ -204,14 +209,14 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
|
||||
int count = countChildren(filter);
|
||||
|
||||
if (count == 0){
|
||||
if (count == 0) {
|
||||
return constructor.newPsiElementArray(0);
|
||||
}
|
||||
|
||||
PsiElement[] result = constructor.newPsiElementArray(count);
|
||||
count = 0;
|
||||
for(ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()){
|
||||
if (filter == null || filter.isInSet(child.getElementType())){
|
||||
for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
if (filter == null || filter.isInSet(child.getElementType())) {
|
||||
result[count++] = SourceTreeToPsiMap.treeElementToPsi(child);
|
||||
}
|
||||
}
|
||||
@@ -223,7 +228,7 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
|
||||
// no lock is needed because all chameleons are expanded already
|
||||
int count = 0;
|
||||
for(ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()){
|
||||
for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
if (filter == null || filter.isInSet(child.getElementType())) {
|
||||
count++;
|
||||
}
|
||||
@@ -237,14 +242,14 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
*/
|
||||
public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
|
||||
ASTNode anchorBefore;
|
||||
if (anchor != null){
|
||||
if (anchor != null) {
|
||||
anchorBefore = before.booleanValue() ? anchor : anchor.getTreeNext();
|
||||
}
|
||||
else{
|
||||
if (before != null && !before.booleanValue()){
|
||||
else {
|
||||
if (before != null && !before.booleanValue()) {
|
||||
anchorBefore = firstChild;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
anchorBefore = null;
|
||||
}
|
||||
}
|
||||
@@ -268,7 +273,7 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
private int myCachedLength = -1;
|
||||
|
||||
public int getTextLength() {
|
||||
if (myCachedLength < 0){
|
||||
if (myCachedLength < 0) {
|
||||
myCachedLength = getLengthInner(SharedImplUtil.findCharTableByTree(this));
|
||||
}
|
||||
if (DebugUtil.CHECK) {
|
||||
@@ -286,13 +291,13 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
}
|
||||
|
||||
protected int getLengthInner(CharTable charTableByTree) {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
int length = 0;
|
||||
for (TreeElement child = firstChild; child != null; child = child.getTreeNext()) {
|
||||
length += child.getTextLength(charTableByTree);
|
||||
}
|
||||
return length;
|
||||
synchronized (PsiLock.LOCK) {
|
||||
int length = 0;
|
||||
for (TreeElement child = firstChild; child != null; child = child.getTreeNext()) {
|
||||
length += child.getTextLength(charTableByTree);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCachedLength(int length) {
|
||||
@@ -311,6 +316,10 @@ public class CompositeElement extends TreeElement implements Cloneable{
|
||||
ChangeUtil.addChild(this, (TreeElement)child, (TreeElement)anchorBefore);
|
||||
}
|
||||
|
||||
public void addChild(ASTNode child) {
|
||||
ChangeUtil.addChild(this, (TreeElement)child, null);
|
||||
}
|
||||
|
||||
public void removeChild(ASTNode child) {
|
||||
ChangeUtil.removeChild(this, (TreeElement)child);
|
||||
}
|
||||
|
||||
@@ -10,15 +10,18 @@ import sun.plugin.dom.exception.InvalidStateException;
|
||||
|
||||
public abstract class LeafElement extends TreeElement {
|
||||
private volatile int myState = 0; // 16 bit for type, 15 bit for state and 1 bit for parentFlag
|
||||
|
||||
public abstract char charAt(int position);
|
||||
|
||||
public abstract int searchWord(int startOffset, StringSearcher searcher);
|
||||
|
||||
public abstract int copyTo(char[] buffer, int start);
|
||||
|
||||
public int copyTo(char[] buffer, int start, CharTable table){
|
||||
public int copyTo(char[] buffer, int start, CharTable table) {
|
||||
return copyTo(buffer, start);
|
||||
}
|
||||
|
||||
public int getTextLength(CharTable table){
|
||||
public int getTextLength(CharTable table) {
|
||||
return getTextLength();
|
||||
}
|
||||
|
||||
@@ -36,10 +39,10 @@ public abstract class LeafElement extends TreeElement {
|
||||
|
||||
public abstract int textMatches(CharSequence buffer, int start);
|
||||
|
||||
public void registerInCharTable(CharTable table, CharTable oldCharTab) {}
|
||||
public void registerInCharTable(CharTable table, CharTable oldCharTab) { }
|
||||
|
||||
//boolean isLast = false;
|
||||
public synchronized void setState(int state){
|
||||
public synchronized void setState(int state) {
|
||||
myState = myState & 0x8000FFFF | (((state + 1) & 0x7FFF) << 16);
|
||||
}
|
||||
|
||||
@@ -49,58 +52,60 @@ public abstract class LeafElement extends TreeElement {
|
||||
return IElementType.find(sh);
|
||||
}
|
||||
|
||||
public int getState(){
|
||||
public int getState() {
|
||||
return (myState >> 16) & 0x7FFF - 1;
|
||||
}
|
||||
|
||||
private boolean isLast(){
|
||||
private boolean isLast() {
|
||||
return (myState & 0x80000000) != 0;
|
||||
}
|
||||
|
||||
private void setLast(boolean last){
|
||||
if(last)
|
||||
private void setLast(boolean last) {
|
||||
if (last) {
|
||||
myState |= 0x80000000;
|
||||
else
|
||||
}
|
||||
else {
|
||||
myState &= 0x7FFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized TreeElement getTreeNext() {
|
||||
if(!isLast()) return next;
|
||||
if (!isLast()) return next;
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized CompositeElement getTreeParent() {
|
||||
if(isLast()) return (CompositeElement)next;
|
||||
if (isLast()) return (CompositeElement)next;
|
||||
|
||||
TreeElement next = this.next;
|
||||
while(next instanceof LeafElement && !((LeafElement)next).isLast()) next = next.next;
|
||||
if(next != null) return next.getTreeParent();
|
||||
while (next instanceof LeafElement && !((LeafElement)next).isLast()) next = next.next;
|
||||
if (next != null) return next.getTreeParent();
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized TreeElement getTreePrev() {
|
||||
final CompositeElement parent = getTreeParent();
|
||||
if(parent == null) return null;
|
||||
if (parent == null) return null;
|
||||
TreeElement firstChild = parent.firstChild;
|
||||
if(firstChild == this) return null;
|
||||
while(firstChild != null && firstChild.next != this) firstChild = firstChild.next;
|
||||
if (firstChild == this) return null;
|
||||
while (firstChild != null && firstChild.next != this) firstChild = firstChild.next;
|
||||
return firstChild;
|
||||
}
|
||||
|
||||
public synchronized void setTreeParent(CompositeElement parent) {
|
||||
if(next == null || isLast()){
|
||||
if (next == null || isLast()) {
|
||||
next = parent;
|
||||
setLast(true);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setTreeNext(TreeElement next) {
|
||||
if(next != null){
|
||||
if (next != null) {
|
||||
setLast(false);
|
||||
this.next = next;
|
||||
}
|
||||
else{
|
||||
if(!isLast()){
|
||||
else {
|
||||
if (!isLast()) {
|
||||
this.next = getTreeParent();
|
||||
setLast(true);
|
||||
}
|
||||
@@ -135,6 +140,10 @@ public abstract class LeafElement extends TreeElement {
|
||||
throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
|
||||
}
|
||||
|
||||
public void addChild(ASTNode child) {
|
||||
throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
|
||||
}
|
||||
|
||||
public void removeChild(ASTNode child) {
|
||||
throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.intellij.lang.ASTNode;
|
||||
public class LeafPsiElement extends LeafElementImpl implements PsiElement {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.LeafPsiElement");
|
||||
|
||||
protected LeafPsiElement(IElementType type, char[] buffer, int startOffset, int endOffset, int lexerState, CharTable table) {
|
||||
public LeafPsiElement(IElementType type, char[] buffer, int startOffset, int endOffset, int lexerState, CharTable table) {
|
||||
super(type, buffer, startOffset, endOffset, table);
|
||||
setState(lexerState);
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ import com.intellij.lang.ASTNode;
|
||||
public abstract class TreeElement extends ElementBase implements ASTNode, Constants, Cloneable {
|
||||
public static final TreeElement[] EMPTY_ARRAY = new TreeElement[0];
|
||||
protected TreeElement next = null; // this var could be not only next element pointer in ChildElements
|
||||
// use it _VERY_ carefuly!! If you are not sure use apropariate getter (getTreeNext()).
|
||||
// use it _VERY_ carefuly!! If you are not sure use apropariate getter (getTreeNext()).
|
||||
|
||||
public static final Key<PsiManager> MANAGER_KEY = Key.create("Element.MANAGER_KEY");
|
||||
public static final Key<PsiElement> PSI_ELEMENT_KEY = Key.create("Element.PsiElement");
|
||||
|
||||
public Object clone(){
|
||||
public Object clone() {
|
||||
TreeElement clone = (TreeElement)super.clone();
|
||||
clone.clearCaches();
|
||||
clone.next = null;
|
||||
@@ -27,18 +28,18 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Consta
|
||||
|
||||
public ASTNode copyElement() {
|
||||
if (getTreeParent() != null) {
|
||||
CompositeElement parentCopy = (CompositeElement)getTreeParent().copyElement();
|
||||
synchronized (PsiLock.LOCK) {
|
||||
int index = 0;
|
||||
for (ASTNode child = getTreeParent().firstChild; child != this; child = child.getTreeNext()) {
|
||||
index++;
|
||||
}
|
||||
ASTNode child;
|
||||
for (child = parentCopy.firstChild; index > 0; child = child.getTreeNext(), index--) {
|
||||
}
|
||||
//child.putUserData(MANAGER_KEY, getManager()); //?
|
||||
return child;
|
||||
CompositeElement parentCopy = (CompositeElement)getTreeParent().copyElement();
|
||||
synchronized (PsiLock.LOCK) {
|
||||
int index = 0;
|
||||
for (ASTNode child = getTreeParent().firstChild; child != this; child = child.getTreeNext()) {
|
||||
index++;
|
||||
}
|
||||
ASTNode child;
|
||||
for (child = parentCopy.firstChild; index > 0; child = child.getTreeNext(), index--) {
|
||||
}
|
||||
//child.putUserData(MANAGER_KEY, getManager()); //?
|
||||
return child;
|
||||
}
|
||||
}
|
||||
else {
|
||||
final ASTNode clone = (ASTNode)clone();
|
||||
@@ -49,17 +50,17 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Consta
|
||||
|
||||
public PsiManager getManager() {
|
||||
TreeElement element;
|
||||
for(element = this; element.getTreeParent() != null; element = element.getTreeParent()){
|
||||
for (element = this; element.getTreeParent() != null; element = element.getTreeParent()) {
|
||||
}
|
||||
|
||||
if (element instanceof FileElement){ //TODO!!
|
||||
if (element instanceof FileElement) { //TODO!!
|
||||
return element.getManager();
|
||||
}
|
||||
else{
|
||||
else {
|
||||
if (getTreeParent() != null) {
|
||||
return getTreeParent().getManager();
|
||||
}
|
||||
else{
|
||||
else {
|
||||
return getUserData(MANAGER_KEY);
|
||||
}
|
||||
}
|
||||
@@ -70,6 +71,7 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Consta
|
||||
public abstract LeafElement findLeafElementAt(int offset);
|
||||
|
||||
public abstract String getText();
|
||||
|
||||
public abstract String getText(CharTable table);
|
||||
|
||||
public abstract char[] textToCharArray();
|
||||
@@ -77,35 +79,35 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Consta
|
||||
public abstract boolean textContains(char c);
|
||||
|
||||
public TextRange getTextRange() {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
int start = getStartOffset();
|
||||
return new TextRange(start, start + getTextLength());
|
||||
}
|
||||
synchronized (PsiLock.LOCK) {
|
||||
int start = getStartOffset();
|
||||
return new TextRange(start, start + getTextLength());
|
||||
}
|
||||
}
|
||||
|
||||
public int getStartOffset() {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
final CompositeElement parent = getTreeParent();
|
||||
if (parent == null) return 0;
|
||||
int offset = parent.getStartOffset();
|
||||
final CharTable table = SharedImplUtil.findCharTableByTree(this);
|
||||
for (TreeElement element1 = parent.firstChild; element1 != this; element1 = element1.getTreeNext()) {
|
||||
offset += element1.getTextLength(table);
|
||||
}
|
||||
return offset;
|
||||
synchronized (PsiLock.LOCK) {
|
||||
final CompositeElement parent = getTreeParent();
|
||||
if (parent == null) return 0;
|
||||
int offset = parent.getStartOffset();
|
||||
final CharTable table = SharedImplUtil.findCharTableByTree(this);
|
||||
for (TreeElement element1 = parent.firstChild; element1 != this; element1 = element1.getTreeNext()) {
|
||||
offset += element1.getTextLength(table);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
public final int getStartOffsetInParent(){
|
||||
public final int getStartOffsetInParent() {
|
||||
if (getTreeParent() == null) return -1;
|
||||
int offset = 0;
|
||||
for(ASTNode child = getTreeParent().getFirstChildNode(); child != this; child = child.getTreeNext()){
|
||||
for (ASTNode child = getTreeParent().getFirstChildNode(); child != this; child = child.getTreeNext()) {
|
||||
offset += child.getTextLength();
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
public int getTextOffset(){
|
||||
public int getTextOffset() {
|
||||
return getStartOffset();
|
||||
}
|
||||
|
||||
@@ -113,25 +115,25 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Consta
|
||||
return textMatches(this, buffer, startOffset, endOffset) == endOffset;
|
||||
}
|
||||
|
||||
public int textStartsWith(CharSequence buffer, int startOffset, int endOffset){
|
||||
public int textStartsWith(CharSequence buffer, int startOffset, int endOffset) {
|
||||
return textMatches(this, buffer, startOffset, endOffset);
|
||||
}
|
||||
|
||||
private static int textMatches(ASTNode element, CharSequence buffer, int startOffset, int endOffset) {
|
||||
synchronized (PsiLock.LOCK) {
|
||||
if (element instanceof LeafElement) {
|
||||
final LeafElement leaf = (LeafElement)element;
|
||||
return leaf.textMatches(buffer, startOffset);
|
||||
}
|
||||
else {
|
||||
int curOffset = startOffset;
|
||||
for (ASTNode child = element.getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
curOffset = textMatches(child, buffer, curOffset, endOffset);
|
||||
if (curOffset == -1) return -1;
|
||||
}
|
||||
return curOffset;
|
||||
}
|
||||
synchronized (PsiLock.LOCK) {
|
||||
if (element instanceof LeafElement) {
|
||||
final LeafElement leaf = (LeafElement)element;
|
||||
return leaf.textMatches(buffer, startOffset);
|
||||
}
|
||||
else {
|
||||
int curOffset = startOffset;
|
||||
for (ASTNode child = element.getFirstChildNode(); child != null; child = child.getTreeNext()) {
|
||||
curOffset = textMatches(child, buffer, curOffset, endOffset);
|
||||
if (curOffset == -1) return -1;
|
||||
}
|
||||
return curOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean textMatches(CharSequence seq) {
|
||||
@@ -143,7 +145,7 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Consta
|
||||
return textMatches(element.getText());
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
public String toString() {
|
||||
return "Element" + "(" + getElementType().toString() + ")";
|
||||
}
|
||||
|
||||
@@ -159,7 +161,7 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Consta
|
||||
|
||||
public abstract void setTreePrev(TreeElement prev);
|
||||
|
||||
public void setTreeNext(TreeElement next){
|
||||
public void setTreeNext(TreeElement next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
@@ -167,13 +169,13 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Consta
|
||||
|
||||
public abstract int getTextLength(CharTable charTableByTree);
|
||||
|
||||
public void clearCaches(){}
|
||||
public void clearCaches() { }
|
||||
|
||||
public final boolean equals(Object obj){
|
||||
public final boolean equals(Object obj) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
public final int hashCode(){
|
||||
public final int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user