diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java b/platform/lang-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java index 0f66d33a65bc..272fc4aba263 100644 --- a/platform/lang-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java +++ b/platform/lang-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java @@ -28,6 +28,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiInvalidElementAccessException; import com.intellij.psi.impl.CheckUtil; +import com.intellij.psi.impl.PsiElementBase; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiElementBase.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiElementBase.java index 67ac1938be78..21b10e0f0d15 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiElementBase.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiElementBase.java @@ -19,15 +19,25 @@ package com.intellij.psi.impl; import com.intellij.ide.util.PsiNavigationSupport; import com.intellij.navigation.ItemPresentation; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ReflectionCache; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; public abstract class PsiElementBase extends ElementBase implements PsiElement { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiElementBase"); + public PsiElement getFirstChild() { PsiElement[] children = getChildren(); if (children.length == 0) return null; @@ -49,9 +59,10 @@ public abstract class PsiElementBase extends ElementBase implements PsiElement { } public void acceptChildren(@NotNull PsiElementVisitor visitor) { - PsiElement[] children = getChildren(); - for (PsiElement child : children) { + PsiElement child = getFirstChild(); + while (child != null) { child.accept(visitor); + child = child.getNextSibling(); } } @@ -111,7 +122,7 @@ public abstract class PsiElementBase extends ElementBase implements PsiElement { } @NotNull - public final GlobalSearchScope getResolveScope() { + public GlobalSearchScope getResolveScope() { return ResolveScopeManager.getElementResolveScope(this); } @@ -150,4 +161,72 @@ public abstract class PsiElementBase extends ElementBase implements PsiElement { public boolean isEquivalentTo(final PsiElement another) { return this == another; } + + public PsiFile getContainingFile() { + final PsiElement parent = getParent(); + if (parent == null) throw new PsiInvalidElementAccessException(this); + return parent.getContainingFile(); + } + + public boolean isPhysical() { + final PsiElement parent = getParent(); + return parent != null && parent.isPhysical(); + } + + public boolean isWritable() { + final PsiElement parent = getParent(); + return parent != null && parent.isWritable(); + } + + public boolean isValid() { + final PsiElement parent = getParent(); + return parent != null && parent.isValid(); + } + + //Q: get rid of these methods? + public boolean textMatches(@NotNull CharSequence text) { + return Comparing.equal(getText(), text, true); + } + + public boolean textMatches(@NotNull PsiElement element) { + return getText().equals(element.getText()); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + visitor.visitElement(this); + } + + public String getName() { + return null; + } + + @NotNull + protected T notNullChild(T child) { + if (child == null) { + LOG.error(getText() + "\n parent=" + getParent().getText()); + } + return child; + } + + @NotNull + protected T[] findChildrenByClass(Class aClass) { + List result = new ArrayList(); + for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) { + if (ReflectionCache.isInstance(cur, aClass)) result.add((T)cur); + } + return result.toArray((T[]) Array.newInstance(aClass, result.size())); + } + + @Nullable + protected T findChildByClass(Class aClass) { + for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) { + if (ReflectionCache.isInstance(cur, aClass)) return (T)cur; + } + return null; + } + + @NotNull + protected T findNotNullChildByClass(Class aClass) { + return notNullChild(findChildByClass(aClass)); + } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java index a657c734d2b3..cc86b3c40007 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java @@ -499,7 +499,7 @@ public class PostprocessReformattingAspect implements PomModelAspect, Disposable if (!currentNodeGenerated && inGeneratedContext) { if (element.getElementType() == TokenType.WHITE_SPACE) return false; final int oldIndent = CodeEditUtil.getOldIndentation(element); - LOG.assertTrue(oldIndent >= 0, "for not generated items old indentation must be defined"); + LOG.assertTrue(oldIndent >= 0, "for not generated items old indentation must be defined: element " + element); rangesToProcess.add(new ReindentTask(document.createRangeMarker(element.getTextRange()), oldIndent)); inGeneratedContext = false; }