detailed diagnostics why a dom element is invalid

This commit is contained in:
peter
2011-02-09 16:16:56 +01:00
parent 12ea59dbaa
commit 87568772f4
14 changed files with 107 additions and 41 deletions
@@ -36,8 +36,17 @@ public class CollectionElementInvocationHandler extends DomInvocationHandler<Abs
}
@Override
public boolean isValid() {
return super.isValid() && getXmlTag() != null;
protected String checkValidity() {
final String s = super.checkValidity();
if (s != null) {
return s;
}
if (getXmlTag() == null) {
return "no XmlTag for collection element: " + getDomElementType();
}
return null;
}
public final void undefineInternal() {
@@ -329,7 +329,19 @@ public class DomFileElementImpl<T extends DomElement> implements DomFileElement<
}
public final boolean isValid() {
return myFile.isValid() && equals(myManager.getFileElement(myFile));
return checkValidity() == null;
}
@Nullable
public String checkValidity() {
if (!myFile.isValid()) {
return "Invalid file";
}
final DomFileElementImpl<DomElement> fileElement = myManager.getFileElement(myFile);
if (!equals(fileElement)) {
return "file element changed: " + fileElement;
}
return null;
}
@NotNull
@@ -47,6 +47,25 @@ public class DomImplUtil {
private DomImplUtil() {
}
public static void assertValidity(DomElement element, String msg) {
if (element instanceof DomFileElementImpl) {
final String s = ((DomFileElementImpl)element).checkValidity();
if (s != null) {
throw new AssertionError(s);
}
return;
}
final DomInvocationHandler handler = DomManagerImpl.getDomInvocationHandler(element);
assert handler != null;
try {
handler.assertValid();
}
catch (AssertionError e) {
throw new AssertionError(msg + e.getMessage());
}
}
public static boolean isTagValueGetter(final JavaMethod method) {
if (!isGetter(method)) {
return false;
@@ -135,15 +135,16 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
@Nullable
public DomElement getParent() {
checkIsValid();
assertValid();
final DomInvocationHandler handler = getParentHandler();
return handler == null ? null : handler.getProxy();
}
protected final void checkIsValid() {
if (!isValid()) {
LOG.error(myType.toString() + " @" + hashCode() + "\nclass=" + getClass() + "\nxml=" + getXmlElement());
protected final void assertValid() {
final String s = checkValidity();
if (s != null) {
throw new AssertionError(myType.toString() + " @" + hashCode() + "\nclass=" + getClass() + "\nxml=" + getXmlElement() + "; " + s);
}
}
@@ -271,7 +272,7 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
}
public XmlTag ensureTagExists() {
checkIsValid();
assertValid();
XmlTag tag = getXmlTag();
if (tag != null) return tag;
@@ -315,35 +316,50 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
return getXmlTag().createChildTag(localName, tagName.getNamespace(element, getFile()), null, false);
}
public boolean isValid() {
public final boolean isValid() {
return checkValidity() == null;
}
@Nullable
protected String checkValidity() {
ProgressManager.checkCanceled();
final DomParentStrategy parentStrategy = getParentStrategy();
if (!parentStrategy.isValid()) {
return false;
String error = parentStrategy.checkValidity();
if (error != null) {
return "Strategy: " + error;
}
if (myLastModCount == myManager.getPsiModificationCount()) {
return true;
final long modCount = myManager.getPsiModificationCount();
if (myLastModCount == modCount) {
return null;
}
final XmlElement xmlElement = parentStrategy.getXmlElement();
if (xmlElement != null) {
final SemService semService = SemService.getSemService(myManager.getProject());
return rememberValidity(equals(semService.getSemElement(DomManagerImpl.DOM_HANDLER_KEY, xmlElement)));
final DomInvocationHandler actual = semService.getSemElement(DomManagerImpl.DOM_HANDLER_KEY, xmlElement);
if (!equals(actual)) {
return "element changed: " + this + "!=" + actual;
}
myLastModCount = modCount;
return null;
}
final DomInvocationHandler parent = getParentHandler();
return rememberValidity(parent != null && parent.isValid());
}
private boolean rememberValidity(boolean isValid) {
if (isValid) {
myLastModCount = myManager.getPsiModificationCount();
if (parent == null) {
return "no parent: " + getDomElementType();
}
return isValid;
error = parent.checkValidity();
if (error != null) {
return "parent: " + error;
}
myLastModCount = modCount;
return null;
}
@NotNull
public final DomGenericInfoEx getGenericInfo() {
return myGenericInfo;
@@ -576,7 +592,7 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
@NotNull
final AttributeChildInvocationHandler getAttributeChild(final AttributeChildDescriptionImpl description) {
checkIsValid();
assertValid();
final EvaluatedXmlName evaluatedXmlName = createEvaluatedXmlName(description.getXmlName());
final XmlTag tag = getXmlTag();
@@ -732,7 +748,7 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
XmlTag tag = getXmlTag();
if (tag == null) return Collections.emptyList();
checkIsValid();
assertValid();
final List<XmlTag> subTags = tagsGetter.fun(this);
if (subTags.isEmpty()) return Collections.emptyList();
@@ -34,5 +34,6 @@ public interface DomParentStrategy {
@NotNull DomParentStrategy clearXmlElement();
boolean isValid();
@Nullable
String checkValidity();
}
@@ -76,18 +76,23 @@ public class DomRootInvocationHandler extends DomInvocationHandler<AbstractDomCh
}
@Override
public boolean isValid() {
protected String checkValidity() {
final XmlTag tag = (XmlTag)getXmlElement();
if (tag != null && !tag.isValid()) {
return false;
return "invalid root tag";
}
return myParent.isValid();
final String s = myParent.checkValidity();
if (s != null) {
return "root: " + s;
}
return null;
}
@NotNull
public DomFileElementImpl getParent() {
checkIsValid();
assertValid();
return myParent;
}
@@ -69,7 +69,7 @@ public class FixedChildDescriptionImpl extends DomChildDescriptionImpl implement
final List<DomElement> result = new SmartList<DomElement>();
final DomInvocationHandler handler = DomManagerImpl.getDomInvocationHandler(element);
if (handler != null) {
handler.checkIsValid();
handler.assertValid();
for (int i = 0; i < myCount; i++) {
result.add(handler.getFixedChild(Pair.create(this, i)).getProxy());
}
@@ -33,7 +33,7 @@ class GetCompositeCollectionInvocation implements Invocation {
}
public Object invoke(final DomInvocationHandler<?> handler, final Object[] args) throws Throwable {
handler.checkIsValid();
handler.assertValid();
Map<XmlTag,DomElement> map = new THashMap<XmlTag, DomElement>();
for (final CollectionChildDescriptionImpl qname : myQnames) {
for (DomElement element : handler.getCollectionChildren(qname, qname.getTagsGetter())) {
@@ -16,7 +16,7 @@ public class GetFixedChildInvocation implements Invocation {
}
public Object invoke(final DomInvocationHandler<?> handler, final Object[] args) throws Throwable {
handler.checkIsValid();
handler.assertValid();
return handler.getFixedChild(myPair).getProxy();
}
}
@@ -7,7 +7,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
@@ -34,7 +33,7 @@ public class GetInvocation implements Invocation {
}
public Object invoke(final DomInvocationHandler<?> handler, final Object[] args) throws Throwable {
handler.checkIsValid();
handler.assertValid();
if (myConverter == Converter.EMPTY_CONVERTER) {
return getValueInner(handler, myConverter);
}
@@ -73,8 +73,8 @@ public class PhysicalDomParentStrategy implements DomParentStrategy {
return new VirtualDomParentStrategy(parent);
}
public boolean isValid() {
return myElement.isValid();
public String checkValidity() {
return myElement.isValid() ? null : "Invalid PSI";
}
public boolean equals(final Object o) {
@@ -53,8 +53,9 @@ public class RootDomParentStrategy implements DomParentStrategy {
return this;
}
public boolean isValid() {
return myFileElement.isValid();
@Override
public String checkValidity() {
return myFileElement.checkValidity();
}
public boolean equals(final Object o) {
@@ -17,7 +17,7 @@ public class SetInvocation implements Invocation {
}
public Object invoke(final DomInvocationHandler<?> handler, final Object[] args) throws Throwable {
handler.checkIsValid();
handler.assertValid();
final SubTag annotation = handler.getAnnotation(SubTag.class);
final Object arg = args[0];
if (annotation != null && annotation.indicator() && arg instanceof Boolean) {
@@ -72,8 +72,12 @@ public class VirtualDomParentStrategy implements DomParentStrategy {
return this;
}
public synchronized boolean isValid() {
return getModCount() == myModCount;
@Override
public synchronized String checkValidity() {
if (getModCount() == myModCount) {
return null;
}
return "mod count changed";
}
public boolean equals(final Object o) {