← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~paul-lucas/zorba/feature-applied_loc into lp:zorba

 

Paul J. Lucas has proposed merging lp:~paul-lucas/zorba/feature-applied_loc into lp:zorba.

Commit message:
Added "applied at" location to XQueryException.

Requested reviews:
  Paul J. Lucas (paul-lucas)

For more details, see:
https://code.launchpad.net/~paul-lucas/zorba/feature-applied_loc/+merge/137357

Added "applied at" location to XQueryException.
-- 
https://code.launchpad.net/~paul-lucas/zorba/feature-applied_loc/+merge/137357
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'include/zorba/internal/diagnostic.h'
--- include/zorba/internal/diagnostic.h	2012-11-17 18:44:55 +0000
+++ include/zorba/internal/diagnostic.h	2012-12-01 00:08:21 +0000
@@ -45,6 +45,7 @@
  * A %location holds the file location of an error.
  */
 class ZORBA_DLL_PUBLIC location {
+  typedef ztd::explicit_bool explicit_bool;
 public:
   /**
    * The line-number type.
@@ -159,8 +160,8 @@
    *
    * @return Returns \c true only if this %location has been set.
    */
-  operator bool() const {
-    return !!line_;
+  operator explicit_bool::type() const {
+    return explicit_bool::value_of( line_ );
   }
 
   /**

=== modified file 'include/zorba/internal/unique_ptr.h'
--- include/zorba/internal/unique_ptr.h	2012-09-19 21:16:15 +0000
+++ include/zorba/internal/unique_ptr.h	2012-12-01 00:08:21 +0000
@@ -455,8 +455,7 @@
   typedef typename ZORBA_TR1_NS::add_reference<D const>::type
           deleter_const_reference;
 
-  struct pointer_conversion { int valid; };
-  typedef int pointer_conversion::*explicit_bool;
+  typedef zorba::internal::ztd::explicit_bool explicit_bool;
 
 public:
   typedef T element_type;
@@ -512,8 +511,8 @@
     std::swap( storage_, p.storage_ );
   }
 
-  operator explicit_bool() const throw() {
-    return get() ? &pointer_conversion::valid : 0;
+  operator explicit_bool::type() const throw() {
+    return explicit_bool::value_of( get() );
   }
 
 private:

=== modified file 'include/zorba/xquery_exception.h'
--- include/zorba/xquery_exception.h	2012-09-19 21:16:15 +0000
+++ include/zorba/xquery_exception.h	2012-12-01 00:08:21 +0000
@@ -58,6 +58,17 @@
    */
   XQueryException& operator=( XQueryException const &from );
 
+  ////////// source file/line location ////////////////////////////////////////
+
+  /**
+   * Checks whether the XQuery source-code location has been set.
+   *
+   * @return Returns \c true only if said has been set.
+   */
+  bool has_source() const throw() {
+    return source_loc_;
+  }
+
   /**
    * Sets the XQuery source-code URI name, line, and column numbers.
    *
@@ -67,24 +78,14 @@
    * @param line_end The source-code URI end line number.
    * @param column_end The source-code URI end column number.
    */
-  void set_source(
-      char const *uri,
-      line_type line,
-      column_type column = 0,
-      line_type line_end = 0,
-      column_type column_end = 0 );
-
-  /**
-   * Checks whether the XQuery source location has been set.
-   *
-   * @return Returns \c true only if the source location has been set.
-   */
-  bool has_source() const throw() {
-    return source_loc_;
-  }
-
-  /**
-   * Gets the XQuery source URI containing the error.
+  void set_source( char const *uri,
+                   line_type line,
+                   column_type column = 0,
+                   line_type line_end = 0,
+                   column_type column_end = 0 );
+
+  /**
+   * Gets the XQuery source-code URI containing the error.
    *
    * @return Returns said URI or the empty string if unset.
    */
@@ -128,6 +129,84 @@
     return source_loc_.column_end();
   }
 
+  ////////// "applied at" file/line location //////////////////////////////////
+
+  /**
+   * Checks whether the XQuery "applied at" location has been set.
+   *
+   * @return Returns \c true only if the "applied at" location has been set.
+   */
+  bool has_applied() const throw() {
+    return applied_loc_;
+  }
+
+  /**
+   * Sets the XQuery source-code "applied at" URI name, line, and column
+   * numbers.
+   *
+   * @param uri The source-code "applied at" URI name.  If either the null
+   * pointer or the empty string, \c source_uri() is used.
+   * @param line The source-code "applied at" URI line number.
+   * @param column The source-code "applied at" URI column number.
+   * @param line_end The source-code "applied at" URI end line number.
+   * @param column_end The source-code "applied at" URI end column number.
+   */
+  void set_applied( char const *uri,
+                    line_type line,
+                    column_type column = 0,
+                    line_type line_end = 0,
+                    column_type column_end = 0 );
+
+  /**
+   * Gets the XQuery source-code "applied at" URI containing the error.
+   *
+   * @return Returns said URI or the empty string if unset.
+   */
+  char const* applied_uri() const throw() {
+    return applied_loc_.file();
+  }
+
+  /**
+   * Gets the XQuery source-code "applied at" line number containing the error.
+   *
+   * @return Returns said line number or 0 if unset.
+   */
+  line_type applied_line() const throw() {
+    return applied_loc_.line();
+  }
+
+  /**
+   * Gets the XQuery source-code "applied at" column number containing the
+   * error.
+   *
+   * @return Returns said column number or 0 if unset.
+   */
+  column_type applied_column() const throw() {
+    return applied_loc_.column();
+  }
+
+  /**
+   * Gets the XQuery source-code "applied at" end line number containing the
+   * error.
+   *
+   * @return Returns said line number or 0 if unset.
+   */
+  line_type applied_line_end() const throw() {
+    return applied_loc_.line_end();
+  }
+
+  /**
+   * Gets the XQuery source-code "applied at" end column number containing the
+   * error.
+   *
+   * @return Returns said column number or 0 if unset.
+   */
+  column_type applied_column_end() const throw() {
+    return applied_loc_.column_end();
+  }
+
+  ////////// XQuery stack trace ///////////////////////////////////////////////
+
   /**
    * Gets the XQuery stack trace, if any.
    *
@@ -155,6 +234,9 @@
   std::ostream& print( std::ostream &o ) const;
 
 private:
+  typedef internal::diagnostic::location location;
+  typedef internal::diagnostic::parameters parameters;
+
   /**
    * Constructs an %XQueryException.
    *
@@ -168,21 +250,23 @@
   XQueryException( Diagnostic const &diagnostic, char const *raise_file,
                    line_type raise_line, char const *message );
 
-  internal::diagnostic::location source_loc_;
+  location source_loc_;
+  location applied_loc_;
   XQueryStackTrace query_trace_;
 
   friend XQueryException make_xquery_exception(
     char const*, ZorbaException::line_type, Diagnostic const&,
-    internal::diagnostic::parameters const&,
-    internal::diagnostic::location const&
+    parameters const&, location const&
   );
 
   friend XQueryException* new_xquery_exception(
     char const*, ZorbaException::line_type, Diagnostic const&,
-    internal::diagnostic::parameters const&,
-    internal::diagnostic::location const&
+    parameters const&, location const&
   );
 
+  friend void set_applied( ZorbaException&, char const*, line_type, column_type,
+                           line_type, column_type, bool );
+
   friend void set_source( ZorbaException&, char const*, line_type, column_type,
                           line_type, column_type, bool );
 

=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml	2012-11-20 18:17:10 +0000
+++ src/diagnostics/diagnostic_en.xml	2012-12-01 00:08:21 +0000
@@ -2892,6 +2892,10 @@
       <value>already specified</value>
     </entry>
 
+    <entry key="AppliedAt">
+      <value>applied at</value>
+    </entry>
+
     <entry key="ArithOpNotDefinedBetween_23">
       <value>arithmetic operation not defined between types "$2" and "$3"</value>
     </entry>
@@ -4049,7 +4053,6 @@
       <value>: a sub-picture must contain at least one character that is an optional-digit-sign or a member of the decimal-digit-family</value>
     </entry>
     
-
     <entry key="JSON_ILLEGAL_CHARACTER">
       <value>'$2': illegal JSON character${ at 3}</value>
     </entry>

=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp	2012-11-20 18:17:10 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp	2012-12-01 00:08:21 +0000
@@ -514,6 +514,7 @@
   { "~ANNOTATION", "annotation" },
   { "~AllMatchesHasExcludes", "AllMatches contains StringExclude" },
   { "~AlreadySpecified", "already specified" },
+  { "~AppliedAt", "applied at" },
   { "~ArithOpNotDefinedBetween_23", "arithmetic operation not defined between types \"$2\" and \"$3\"" },
   { "~AtomizationHasMoreThanOneValue", "atomization has more than one value" },
   { "~AttributeName", "attribute name" },

=== modified file 'src/diagnostics/pregenerated/dict_zed_keys.h'
--- src/diagnostics/pregenerated/dict_zed_keys.h	2012-11-07 19:28:55 +0000
+++ src/diagnostics/pregenerated/dict_zed_keys.h	2012-12-01 00:08:21 +0000
@@ -79,6 +79,7 @@
 #define ZED_ZWST0005_VARIADIC "~ZWST0005_VARIADIC"
 #define ZED_AllMatchesHasExcludes "~AllMatchesHasExcludes"
 #define ZED_AlreadySpecified "~AlreadySpecified"
+#define ZED_AppliedAt "~AppliedAt"
 #define ZED_ArithOpNotDefinedBetween_23 "~ArithOpNotDefinedBetween_23"
 #define ZED_AtomizationHasMoreThanOneValue "~AtomizationHasMoreThanOneValue"
 #define ZED_AttributeName "~AttributeName"

=== modified file 'src/diagnostics/xquery_exception.cpp'
--- src/diagnostics/xquery_exception.cpp	2012-09-19 21:16:15 +0000
+++ src/diagnostics/xquery_exception.cpp	2012-12-01 00:08:21 +0000
@@ -16,9 +16,14 @@
 
 #include "stdafx.h"
 
-#include <util/fs_util.h>
-#include <util/uri_util.h>
-
+// standard
+#include <cstring>
+
+// Zorba
+#include "util/fs_util.h"
+#include "util/uri_util.h"
+
+// local
 #include "dict.h"
 #include "xquery_exception.h"
 
@@ -72,11 +77,21 @@
   return unique_ptr<ZorbaException>( new XQueryException( *this ) );
 }
 
+void XQueryException::set_applied( char const *uri,
+                                   line_type line,
+                                   column_type col,
+                                   line_type line_end,
+                                   column_type col_end ) {
+  if ( !uri || !*uri )
+    uri = source_loc_.file();
+  applied_loc_.set( uri, line, col, line_end, col_end );
+}
+
 void XQueryException::set_source( char const *uri,
                                   line_type line,
                                   column_type col,
                                   line_type line_end,
-                                  column_type col_end) {
+                                  column_type col_end ) {
   source_loc_.set( uri, line, col, line_end, col_end );
 }
 
@@ -84,36 +99,48 @@
   throw *this;
 }
 
+static bool print_uri( ostream &o, char const *uri ) {
+  if ( uri && *uri ) {
+    switch ( uri::get_scheme( uri ) ) {
+      case uri::none:
+      case uri::file:
+        try {
+          o << '<' << fs::get_normalized_path( uri ) << '>';
+          break;
+        }
+        catch ( ... ) {
+          // fall back to printing as a URI
+        }
+        // no break;
+      default:
+        o << '<' << uri << '>';
+    }
+    return true;
+  }
+  return false;
+}
+
 ostream& XQueryException::print( ostream &o ) const {
   if ( has_source() ) {
+    if ( !print_uri( o, source_uri() ) )
+      o << '(' << diagnostic::dict::lookup( ZED( NoSourceURI ) ) << ')';
+    o << ':' << source_line();
+    if ( source_column() )
+      o << ',' << source_column();
 
-    char const *const u = source_uri();
-    if ( u && *u ) {
-      switch ( uri::get_scheme( u ) ) {
-        case uri::none:
-        case uri::file:
-          try {
-            o << '<' << fs::get_normalized_path( u ) << '>';
-            break;
-          }
-          catch ( ... ) {
-            // fall back to printing as a URI
-          }
-          // no break;
-        default:
-          o << '<' << u << '>';
+    if ( has_applied() ) {
+      o << " (" << diagnostic::dict::lookup( ZED( AppliedAt ) ) << ' ';
+      if ( applied_uri() && ::strcmp( applied_uri(), source_uri() ) != 0 ) {
+        if ( print_uri( o, applied_uri() ) )
+          o << ':';
       }
-    } else
-      o << '(' << diagnostic::dict::lookup( ZED( NoSourceURI ) ) << ')';
-
-    if ( source_line() ) {
-      o << ':' << source_line();
-      if ( source_column() )
-        o << ',' << source_column();
-      o << ':';
+      o << applied_line();
+      if ( applied_column() )
+        o << ',' << applied_column();
+      o << ')';
     }
 
-    o << ' ';
+    o << ": ";
   }
   return ZorbaException::print( o );
 }
@@ -131,11 +158,8 @@
   XQueryException xe( diagnostic, raise_file, raise_line, message.c_str() );
   if ( loc )
     xe.set_source(
-        loc.file(),
-        loc.line(),
-        loc.column(),
-        loc.line_end(),
-        loc.column_end() );
+      loc.file(), loc.line(), loc.column(), loc.line_end(), loc.column_end()
+    );
   return xe;
 }
 
@@ -151,14 +175,29 @@
     new XQueryException( diagnostic, raise_file, raise_line, message.c_str() );
   if ( loc )
     xe->set_source(
-        loc.file(),
-        loc.line(),
-        loc.column(),
-        loc.line_end(),
-        loc.column_end() );
+      loc.file(), loc.line(), loc.column(), loc.line_end(), loc.column_end()
+    );
   return xe;
 }
 
+void set_applied( ZorbaException &ze, char const *file,
+                  XQueryException::line_type line,
+                  XQueryException::column_type col,
+                  XQueryException::line_type line_end,
+                  XQueryException::column_type col_end,
+                  bool overwrite ) {
+  if ( XQueryException *const xe = dynamic_cast<XQueryException*>( &ze ) ) {
+    if ( !xe->has_applied() || overwrite )
+      xe->set_applied( file, line, col, line_end, col_end );
+  } else {
+    XQueryException new_xe(
+      ze.diagnostic(), ze.raise_file(), ze.raise_line(), ze.what()
+    );
+    new_xe.set_applied( file, line, col, line_end, col_end );
+    throw new_xe;
+  }
+}
+
 void set_source( ZorbaException &ze, char const *file,
                  XQueryException::line_type line,
                  XQueryException::column_type col,

=== modified file 'src/diagnostics/xquery_exception.h'
--- src/diagnostics/xquery_exception.h	2012-09-19 21:16:15 +0000
+++ src/diagnostics/xquery_exception.h	2012-12-01 00:08:21 +0000
@@ -232,6 +232,106 @@
   }
 }
 
+////////// XQuery diagnostic "applied at" location ////////////////////////////
+
+/**
+ * Sets the XQuery source location of the given ZorbaException but only if it's
+ * actually an XQueryException.  If it's actually a ZorbaException, constructs
+ * a new XQueryException (copying the information from the ZorbaException) and
+ * throws it.
+ *
+ * @param ze The ZorbaException to set the location of.
+ * @param file The XQuery file name.
+ * @param line The line number.
+ * @param col The column number.
+ * @param line_end The end line number.
+ * @param col_end The end column number.
+ * @param overwrite If \c false, sets the location only if the exception
+ * doesn't already have one; if \c true, always sets the location even if the
+ * exception already has one.
+ */
+void set_applied( ZorbaException &ze, char const *file,
+                  XQueryException::line_type line,
+                  XQueryException::column_type col,
+                  XQueryException::line_type line_end,
+                  XQueryException::column_type col_end,
+                  bool overwrite = true );
+
+/**
+ * Sets the XQuery source location of the given ZorbaException but only if it's
+ * actually an XQueryException.
+ *
+ * @tparam StringType The \a file string type.
+ * @param ze The ZorbaException to set the location of.
+ * @param file The XQuery file name.
+ * @param line The line number.
+ * @param col The column number.
+ * @param line_end The end line number.
+ * @param col_end The end column number.
+ * @param overwrite If \c false, sets the location only if the exception
+ * doesn't already have one; if \c true, always sets the location even if the
+ * exception already has one.
+ */
+template<class StringType> inline
+void set_applied( ZorbaException &ze, StringType const &file,
+                 XQueryException::line_type line,
+                 XQueryException::column_type col,
+                 XQueryException::line_type line_end,
+                 XQueryException::column_type col_end,
+                 bool overwrite = true ) {
+  set_applied( ze, file.c_str(), line, col, line_end, col_end, overwrite );
+}
+
+/**
+ * Sets the XQuery source location of the given ZorbaException but only if it's
+ * actually an XQueryException.
+ *
+ * @param ze The ZorbaException to set the location of.
+ * @param loc The query location.
+ * @param overwrite If \c false, sets the location only if the exception
+ * doesn't already have one; if \c true, always sets the location even if the
+ * exception already has one.
+ */
+inline void set_applied( ZorbaException &ze, QueryLoc const &loc,
+                        bool overwrite = true ) {
+  set_applied(
+    ze,
+    loc.getFilename(),
+    loc.getLineBegin(),
+    loc.getColumnBegin(),
+    loc.getLineEnd(),
+    loc.getColumnEnd(),
+    overwrite
+  );
+}
+
+/**
+ * Sets the XQuery source location of the given ZorbaException but only if it's
+ * actually an XQueryException.
+ *
+ * @param to The ZorbaException to set the location of.
+ * @param from The ZorbaException to get the location from but only if it's
+ * actually an XQueryException.
+ * @param overwrite If \c false, sets the location only if the exception
+ * doesn't already have one; if \c true, always sets the location even if the
+ * exception already has one.
+ */
+inline void set_applied( ZorbaException &to, ZorbaException const &from,
+                        bool overwrite = true ) {
+  if ( XQueryException const *const xe =
+        dynamic_cast<XQueryException const*>( &from ) ) {
+    set_applied(
+      to,
+      xe->source_uri(),
+      xe->source_line(),
+      xe->source_column(),
+      xe->source_line_end(),
+      xe->source_column_end(),
+      overwrite
+    );
+  }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 } // namespace zorba

=== modified file 'src/runtime/core/apply_updates.cpp'
--- src/runtime/core/apply_updates.cpp	2012-11-26 15:39:32 +0000
+++ src/runtime/core/apply_updates.cpp	2012-12-01 00:08:21 +0000
@@ -235,45 +235,9 @@
   catch (XQueryException& e)
   {
     if ( e.has_source() )
-    {
-      Diagnostic const &d = e.diagnostic();
-      if ( d == err::XUDY0021
-        || d == err::XUDY0024
-        || d == jerr::JNUP0006
-        || d == zerr::ZDDY0013_COLLECTION_BAD_DESTROY_INDEXES
-        || d == zerr::ZDDY0014_COLLECTION_BAD_DESTROY_ICS
-        || d == zerr::ZDDY0015_COLLECTION_BAD_DESTROY_NODES
-        || d == zerr::ZDDY0028_INDEX_DOMAIN_HAS_DUPLICATE_NODES
-        || d == zerr::ZDDY0023_INDEX_DOES_NOT_EXIST
-        || d == zerr::ZSTR0060_RANGE_EXCEPTION )
-      {
-        try {
-          QueryLoc loc2( loc );
-          loc2.setFilename( fs::base_name( loc.getFilename() ) );
-          throw XQUERY_EXCEPTION(
-            err::XUDY0021,
-            ERROR_PARAMS( e.what(), ZED( XUDY0021_AppliedAt ), loc2 ),
-            ERROR_LOC( e )
-          );
-        }
-        catch ( XQueryException &e2 ) {
-          //
-          // This extra try/catch is used so that we can use the error
-          // dictionary value string of XUDY0021 to format the error message,
-          // but then set the actual error code back to that of the original
-          // exception.
-          //
-          e2.set_diagnostic( d );
-          throw;
-        }
-      }
-    }
+      set_applied( e, loc );
     else
-    {
-      // exception raised by the store doesn't have a store location
-      // hence, we add the location of the apply expression
-      set_source(e, loc);
-    }
+      set_source( e, loc );
     throw;
   }
 }


Follow ups