Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(552)

Unified Diff: runtime/vm/object.cc

Issue 68113028: Lazily format LanguageError messages (fix issue 15069). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 30304)
+++ runtime/vm/object.cc (working copy)
@@ -1682,28 +1682,18 @@
}
-static RawError* FormatError(const Error& prev_error,
- const Script& script,
- intptr_t token_pos,
- const char* format, ...) {
- va_list args;
- va_start(args, format);
- if (prev_error.IsNull()) {
- return Parser::FormatError(script, token_pos, "Error", format, args);
- } else {
- return Parser::FormatErrorWithAppend(prev_error, script, token_pos,
- "Error", format, args);
- }
-}
-
static void ReportTooManyTypeArguments(const Class& cls) {
const Error& error = Error::Handle(
- FormatError(Error::Handle(), // No previous error.
- Script::Handle(cls.script()), cls.token_pos(),
- "too many type parameters declared in class '%s' or in its "
- "super classes",
- String::Handle(cls.Name()).ToCString()));
+ LanguageError::NewFormatted(
+ Error::Handle(), // No previous error.
+ Script::Handle(cls.script()),
+ cls.token_pos(),
+ LanguageError::kError,
+ Heap::kNew,
+ "too many type parameters declared in class '%s' or in its "
+ "super classes",
+ String::Handle(cls.Name()).ToCString()));
Isolate::Current()->long_jump_base()->Jump(1, error);
UNREACHABLE();
}
@@ -2240,9 +2230,13 @@
orig_func.UserVisibleSignature()) {
// Compare user visible signatures to ignore different implicit parameters
// when patching a constructor with a factory.
- *error = FormatError(*error, // No previous error.
- Script::Handle(patch.script()), func.token_pos(),
- "signature mismatch: '%s'", member_name.ToCString());
+ *error = LanguageError::NewFormatted(
+ *error, // No previous error.
+ Script::Handle(patch.script()),
+ func.token_pos(),
+ LanguageError::kError,
+ Heap::kNew,
+ "signature mismatch: '%s'", member_name.ToCString());
return false;
}
}
@@ -2281,9 +2275,13 @@
// Verify no duplicate additions.
orig_field ^= LookupField(member_name);
if (!orig_field.IsNull()) {
- *error = FormatError(*error, // No previous error.
- Script::Handle(patch.script()), field.token_pos(),
- "duplicate field: %s", member_name.ToCString());
+ *error = LanguageError::NewFormatted(
+ *error, // No previous error.
+ Script::Handle(patch.script()),
+ field.token_pos(),
+ LanguageError::kError,
+ Heap::kNew,
+ "duplicate field: %s", member_name.ToCString());
return false;
}
new_list.SetAt(i, field);
@@ -4852,10 +4850,12 @@
other, Object::null_abstract_type_arguments(), bound_error)) {
// For more informative error reporting, use the location of the other
// function here, since the caller will use the location of this function.
- *bound_error = FormatError(
+ *bound_error = LanguageError::NewFormatted(
*bound_error, // A bound error if non null.
Script::Handle(other.script()),
other.token_pos(),
+ LanguageError::kError,
+ Heap::kNew,
"signature type '%s' of function '%s' is not a subtype of signature "
"type '%s' of function '%s'",
String::Handle(UserVisibleSignature()).ToCString(),
@@ -10679,7 +10679,13 @@
}
-RawLanguageError* LanguageError::New(const String& message, Heap::Space space) {
+RawLanguageError* LanguageError::NewFormattedV(const Error& prev_error,
+ const Script& script,
+ intptr_t token_pos,
+ Kind kind,
+ Heap::Space space,
+ const char* format,
+ va_list args) {
ASSERT(Object::language_error_class() != Class::null());
LanguageError& result = LanguageError::Handle();
{
@@ -10689,18 +10695,151 @@
NoGCScope no_gc;
result ^= raw;
}
- result.set_message(message);
+ result.set_previous_error(prev_error);
+ result.set_script(script);
+ result.set_token_pos(token_pos);
+ result.set_kind(kind);
+ result.set_message(String::Handle(String::NewFormattedV(format, args)));
return result.raw();
}
-void LanguageError::set_message(const String& message) const {
- StorePointer(&raw_ptr()->message_, message.raw());
+RawLanguageError* LanguageError::NewFormatted(const Error& prev_error,
+ const Script& script,
+ intptr_t token_pos,
+ Kind kind,
+ Heap::Space space,
+ const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ RawLanguageError* result = LanguageError::NewFormattedV(
+ prev_error, script, token_pos, kind, space, format, args);
+ NoGCScope no_gc;
+ va_end(args);
+ return result;
}
+RawLanguageError* LanguageError::New(const String& formatted_message,
+ Heap::Space space) {
+ ASSERT(Object::language_error_class() != Class::null());
+ LanguageError& result = LanguageError::Handle();
+ {
+ RawObject* raw = Object::Allocate(LanguageError::kClassId,
+ LanguageError::InstanceSize(),
+ space);
+ NoGCScope no_gc;
+ result ^= raw;
+ }
+ result.set_formatted_message(formatted_message);
+ return result.raw();
+}
+
+
+void LanguageError::set_previous_error(const Error& value) const {
+ StorePointer(&raw_ptr()->previous_error_, value.raw());
+}
+
+
+void LanguageError::set_script(const Script& value) const {
+ StorePointer(&raw_ptr()->script_, value.raw());
+}
+
+
+void LanguageError::set_token_pos(intptr_t value) const {
+ ASSERT(value >= 0);
+ raw_ptr()->token_pos_ = value;
+}
+
+
+void LanguageError::set_kind(uint8_t value) const {
+ raw_ptr()->kind_ = value;
+}
+
+
+void LanguageError::set_message(const String& value) const {
+ StorePointer(&raw_ptr()->message_, value.raw());
+}
+
+
+void LanguageError::set_formatted_message(const String& value) const {
+ StorePointer(&raw_ptr()->formatted_message_, value.raw());
+}
+
+
+RawString* LanguageError::FormatMessage() const {
+ if (formatted_message() != String::null()) {
+ return formatted_message();
+ }
+ const char* message_header;
+ switch (kind()) {
+ case kWarning: message_header = "warning"; break;
+ case kError: message_header = "error"; break;
+ case kMalformedType: message_header = "malformed type"; break;
+ case kMalboundedType: message_header = "malbounded type"; break;
+ default: message_header = ""; UNREACHABLE();
+ }
+ String& result = String::Handle();
+ String& msg = String::Handle(message());
+ const Script& scr = Script::Handle(script());
+ if (!scr.IsNull()) {
+ const String& script_url = String::Handle(scr.url());
+ if (token_pos() >= 0) {
+ intptr_t line, column;
+ scr.GetTokenLocation(token_pos(), &line, &column);
+ // Only report the line position if we have the original source. We still
+ // need to get a valid column so that we can report the ^ mark below the
+ // snippet.
+ if (scr.HasSource()) {
+ result = String::NewFormatted("'%s': %s: line %" Pd " pos %" Pd ": ",
+ script_url.ToCString(),
+ message_header,
+ line,
+ column);
+ } else {
+ result = String::NewFormatted("'%s': %s: line %" Pd ": ",
+ script_url.ToCString(),
+ message_header,
+ line);
+ }
+ // Append the formatted error or warning message.
+ result = String::Concat(result, msg);
+ // Append the source line.
+ const String& script_line = String::Handle(scr.GetLine(line));
+ ASSERT(!script_line.IsNull());
+ result = String::Concat(result, Symbols::NewLine());
+ result = String::Concat(result, script_line);
+ result = String::Concat(result, Symbols::NewLine());
+ // Append the column marker.
+ const String& column_line = String::Handle(
+ String::NewFormatted("%*s\n", static_cast<int>(column), "^"));
+ result = String::Concat(result, column_line);
+ } else {
+ // Token position is unknown.
+ result = String::NewFormatted("'%s': %s: ",
+ script_url.ToCString(),
+ message_header);
+ result = String::Concat(result, msg);
+ }
+ } else {
+ // Script is unknown.
+ // Append the formatted error or warning message.
+ result = String::NewFormatted("%s: ", message_header);
+ result = String::Concat(result, msg);
+ }
+ // Prepend previous error message.
+ const Error& prev_error = Error::Handle(previous_error());
+ if (!prev_error.IsNull()) {
+ msg = String::New(prev_error.ToErrorCString());
+ result = String::Concat(msg, result);
+ }
+ set_formatted_message(result);
+ return result.raw();
+}
+
+
const char* LanguageError::ToErrorCString() const {
- const String& msg_str = String::Handle(message());
+ const String& msg_str = String::Handle(FormatMessage());
return msg_str.ToCString();
}
@@ -12134,10 +12273,12 @@
const Script& script = Script::Handle(cls.script());
// Since the bound may have been canonicalized, its token index is
// meaningless, therefore use the token index of this type parameter.
- *bound_error = FormatError(
+ *bound_error = LanguageError::NewFormatted(
*bound_error,
script,
token_pos(),
+ LanguageError::kMalboundedType,
+ Heap::kNew,
"type parameter '%s' of class '%s' must extend bound '%s', "
"but type argument '%s' is not a subtype of '%s'\n",
type_param_name.ToCString(),
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698