[86383] Added correction for line numbers. In some circumstances the end element is identified as the location to report errors. This fix corrects the location to be that of the starting element.
Added tests for the line adjustments.
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ValidatorHelper.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ValidatorHelper.java
index acce777..8ab5667 100644
--- a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ValidatorHelper.java
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ValidatorHelper.java
@@ -109,6 +109,11 @@
*/
private class InternalErrorHandler implements org.xml.sax.ErrorHandler
{
+ public InternalErrorHandler()
+ {
+ super();
+ }
+
public void error(SAXParseException exception) throws SAXException
{
}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationInfo.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationInfo.java
index 6457db9..9f77806 100644
--- a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationInfo.java
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2001, 2004 IBM Corporation and others.
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,14 +11,14 @@
package org.eclipse.wst.xml.core.internal.validation;
+import java.util.Stack;
+
import org.apache.xerces.xni.XMLLocator;
import org.eclipse.wst.xml.core.internal.validation.core.ValidationInfo;
/**
* A validation information object specific to XML validators.
- *
- * @author Lawrence Mandel, IBM
*/
public class XMLValidationInfo extends ValidationInfo implements XMLValidationReport
{
@@ -31,6 +31,12 @@
protected XMLLocator locator = null;
/**
+ * A stack of start tag locations, used to move errors
+ * reported at the close tag to be reported at the start tag.
+ */
+ protected Stack startElementLocations = new Stack();
+
+ /**
* Constructor.
*
* @param uri The URI of the file this report describes.
@@ -153,4 +159,15 @@
this.messageArguments = messageArguments;
}
+ /**
+ * Get the start elements locations.
+ *
+ * @return
+ * A stack containing the start element locations.
+ */
+ protected Stack getStartElementLocations()
+ {
+ return startElementLocations;
+ }
+
}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidator.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidator.java
index 8b34ad2..12160e0 100644
--- a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidator.java
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidator.java
@@ -24,9 +24,15 @@
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.parsers.StandardParserConfiguration;
+import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XNIException;
@@ -57,6 +63,7 @@
//protected MyEntityResolver entityResolver = null;
protected ErrorCustomizationManager errorCustomizationManager;
protected Hashtable ingoredErrorKeyTable = new Hashtable();
+ protected Set adjustLocationErrorKeySet = new TreeSet();
protected static final String IGNORE_ALWAYS = "IGNORE_ALWAYS"; //$NON-NLS-1$
protected static final String IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL = "IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL"; //$NON-NLS-1$
@@ -79,6 +86,14 @@
ingoredErrorKeyTable.put(PREMATURE_EOF, IGNORE_ALWAYS);
ingoredErrorKeyTable.put(ROOT_ELEMENT_TYPE_MUST_MATCH_DOCTYPEDECL, IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL);
ingoredErrorKeyTable.put(MSG_ELEMENT_NOT_DECLARED, IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL);
+
+ // Here we add some error keys that we need to adjust the location information for.
+ // The location information will be adjusted to place the message on the line of the starting
+ // element instead of on the line of the closing element.
+ adjustLocationErrorKeySet.add("MSG_CONTENT_INVALID");
+ adjustLocationErrorKeySet.add("MSG_CONTENT_INCOMPLETE");
+ adjustLocationErrorKeySet.add("cvc-complex-type.2.4.b");
+ adjustLocationErrorKeySet.add("cvc-complex-type.2.3");
}
/**
@@ -110,11 +125,34 @@
StandardParserConfiguration configuration = new MyStandardParserConfiguration(valinfo);
reader = new org.apache.xerces.parsers.SAXParser(configuration)
{
+ private XMLLocator locator = null;
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.parsers.AbstractSAXParser#startDocument(org.apache.xerces.xni.XMLLocator, java.lang.String, org.apache.xerces.xni.NamespaceContext, org.apache.xerces.xni.Augmentations)
+ */
public void startDocument(org.apache.xerces.xni.XMLLocator theLocator, java.lang.String encoding, NamespaceContext nscontext, org.apache.xerces.xni.Augmentations augs)
{
+ locator = theLocator;
valinfo.setXMLLocator(theLocator);
super.startDocument(theLocator, encoding, nscontext, augs);
}
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.parsers.AbstractSAXParser#startElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.XMLAttributes, org.apache.xerces.xni.Augmentations)
+ */
+ public void startElement(QName arg0, XMLAttributes arg1, Augmentations arg2) throws XNIException
+ {
+ valinfo.getStartElementLocations().push(new LocationCoordinate(locator.getLineNumber(), locator.getColumnNumber()));
+ super.startElement(arg0, arg1, arg2);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.parsers.AbstractSAXParser#endElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.Augmentations)
+ */
+ public void endElement(QName arg0, Augmentations arg1) throws XNIException {
+ super.endElement(arg0, arg1);
+ valinfo.getStartElementLocations().pop();
+ }
};
reader.setFeature("http://apache.org/xml/features/continue-after-fatal-error", false); //$NON-NLS-1$
@@ -444,13 +482,26 @@
{
if(exception.getSystemId() != null)
{
+ int lineNumber = exception.getLineNumber();
+ int columnNumber = exception.getColumnNumber();
+
+ // For the following three errors the line number will be modified to use that of the start
+ // tag instead of the end tag.
+ String currentErrorKey = valinfo.currentErrorKey;
+ if (currentErrorKey != null && adjustLocationErrorKeySet.contains(currentErrorKey))
+ {
+ LocationCoordinate adjustedCoordinates = (LocationCoordinate)valinfo.getStartElementLocations().peek();
+ lineNumber = adjustedCoordinates.getLineNumber();
+ columnNumber = adjustedCoordinates.getColumnNumner();
+ }
+
if(severity == WARNING)
{
- valinfo.addWarning(exception.getLocalizedMessage(), exception.getLineNumber(), exception.getColumnNumber(), exception.getSystemId());
+ valinfo.addWarning(exception.getLocalizedMessage(), lineNumber, columnNumber, exception.getSystemId());
}
else
{
- valinfo.addError(exception.getLocalizedMessage(), exception.getLineNumber(), exception.getColumnNumber(), exception.getSystemId(), valinfo.getCurrentErrorKey(), valinfo.getMessageArguments());
+ valinfo.addError(exception.getLocalizedMessage(), lineNumber, columnNumber, exception.getSystemId(), valinfo.getCurrentErrorKey(), valinfo.getMessageArguments());
}
}
}
@@ -597,4 +648,29 @@
};
}
}
+
+ /**
+ * A line and column number coordinate.
+ */
+ protected class LocationCoordinate
+ {
+ private int lineNo = -1;
+ private int columnNo = -1;
+
+ public LocationCoordinate(int lineNumber, int columnNumber)
+ {
+ this.lineNo = lineNumber;
+ this.columnNo = columnNumber;
+ }
+
+ public int getLineNumber()
+ {
+ return this.lineNo;
+ }
+
+ public int getColumnNumner()
+ {
+ return this.columnNo;
+ }
+ }
}