Project

Profile

Help

Bug #5407

closed

XX compiler outputs its own location on an error

Added by Michael Kay about 2 years ago. Updated almost 2 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
XX compiler
Sprint/Milestone:
-
Start date:
2022-03-18
Due date:
% Done:

100%

Estimated time:
Applies to JS Branch:
2, Trunk
Fix Committed on JS Branch:
2, Trunk
Fixed in JS Release:
SEF Generated with:
Platforms:
Company:
-
Contact person:
-
Additional contact persons:
-

Description

When the XX compiler detects an error, typical output might be

Compiling stylesheet /Users/mike/GitHub/saxon-js-enterprise/src/test/testdriver/testdriverNodeJS.xsl
Failed to compile stylesheet: No binding for variable Q{}message-level
Error XPST0008 at static.xsl#1057
    Failed to compile stylesheet:
Error XPST0008 at static.xsl#1057
    No binding for variable Q{}message-level

Several problems here:

(a) there's no indication of where we are in the stylesheet being compiled

(b) We don't need to know the location in the compiler where the error was detected (static.xsl#1057)

(c) We certainly don't need to be told twice.

Note: the actual error was a static variable being referenced before the declaration.

Actions #1

Updated by Michael Kay about 2 years ago

  • Description updated (diff)
Actions #2

Updated by Michael Kay about 2 years ago

A possible remedy might be an extension attribute on xsl:message indicating that the location information should be the location of the context node in the source document, not the location of the xsl:message instruction in the stylesheet.

Actions #3

Updated by Michael Kay about 2 years ago

There are two sides to this: (a) ensuring that the actual error location is added to the message, and (b) removing the messages giving the location in the compiler.

As regards (a), many static errors, in particular errors in XPath expressions, do include this information. But there are many cases where it is missing -- one example is syntax errors in match patterns. Any call on error() that does not include a call on f:line-loc() is suspect.

As regards (b), the error is output using fn:error(), not using xsl:message. In some cases the call is to fn:syntax-error(), which then calls fn:error(). Unfortunately it's not possible to enhance fn:syntax-error to add the current processing location, because user functions don't get the context item as a parameter. The display of the compiler location detecting the error comes from XError.getMessage().

Actions #4

Updated by Michael Kay about 2 years ago

Let's focus on a specific example. I have a stylesheet with a (deliberate) conflict between xsl:strip-space and xsl:preserve-space. With -t, the XX compiler output is:

Failed to compile stylesheet: Conflicting strip and preserve space declarations for Q{}a at highest import precedence
Error Q{http://www.w3.org/2005/xqt-errors}XTSE0270 at XSLT-SEF-compiler.xsl#1490
    Failed to compile stylesheet:
Error Q{http://www.w3.org/2005/xqt-errors}XTSE0270 at XSLT-SEF-compiler.xsl#1490
    Conflicting strip and preserve space declarations for Q{}a at highest import precedence

Where do these redundant messages come from?

The error is detected in XSLT-SEF-compiler.xsl line 1535 (so the #1490 isn't even accurate...) and results in a call on the function f:syntax-error(), which is in lib.xsl line 223 (I guess f:syntax-error got inlined, which is why the location doesn't appear), and this in turn calls fn:error().

Some of the junk output comes from command.js line 369.

(Note: to rebuild the command line, gradle task setupNode seems to do the trick...)

With a bit of tweaking to command.js the output is now

Failed to compile stylesheet
Error Q{http://www.w3.org/2005/xqt-errors}XTSE0270 at XSLT-SEF-compiler.xsl#1490
    Conflicting strip and preserve space declarations for Q{}a at highest import precedence

To add the actual location of the error, we need to add information at the point where it is detected.

Removing the internal compiler location is a bit trickier.

The fact that the location is present implies that XError.expr is set in the XError object created when fn:error() is called. But it's not obvious where this comes from: in the compiler, lib.xsl line 227 is calling the two-argument form of fn:error(), and in CoreFn.js, error() calls the two-argument constructor for XError(), which leaves expr as null. I guess the XError is being caught somewhere, augmented, and re-thrown.

Sure enough, there are a number of places where this happens, for example in Expr.evaluateWithoutTrace(), and in Push.push(). The code here is necessary to add diagnostics for ordinary dynamic errors that occur during transformation; it's unfortunate that we don't want it here, because the transformation hasn't actually "failed" in that sense.

Actions #5

Updated by Michael Kay about 2 years ago

I've changed the XError class to expose the parts through methods getErrorCode(), getRawMessage(), getOriginatingLineNumber() etc. When a compile error occurs, command.js instead of simply outputting e.getMessage() can construct a message from these parts: in particular, it can omit the location information, which is not useful.

With this change, the output is:

XTSE0270: Conflicting strip and preserve space declarations for Q{}a at highest import precedence
Failed to compile stylesheet

It now remains to add the actual location information in the user stylesheet.

Actions #6

Updated by Michael Kay about 2 years ago

I've achieved this as follows:

(a) when the error is detected, call f:syntax-error-at#3, with the third argument being set to the node where the failure was detected

(b) change f:syntax-error-at#3 to call error#3, with the third argument being the result of f:line-loc() applied to this node

(c) change the code in command.js that formats the error message to include the value of error.errorObject

The result is the message

Error XTSE0270 on line 6 in temp/test.xsl:
  Conflicting strip and preserve space declarations for Q{}a at highest import precedence
Failed to compile stylesheet

Now all that remains (!) is to change other places where static errors are detected to use the same logic.

Actions #7

Updated by Michael Kay about 2 years ago

  • Status changed from New to Resolved
  • Fix Committed on JS Branch 2, Trunk added

Largely fixed; most errors now have location information.

The other limitation in this area, which I haven't addressed, is that we're generally only reporting a single static error in one compilation run. Fixing that is a fair bit of extra work.

Actions #8

Updated by Debbie Lockett almost 2 years ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in JS Release set to SaxonJS 2.4

Bug fix applied in the SaxonJS 2.4 maintenance release.

Please register to edit this issue

Also available in: Atom PDF Tracking page