From 4ed56d8a1dc8a4f1bb029e9851a2ab203b67b6b7 Mon Sep 17 00:00:00 2001 From: Herman Venter Date: Thu, 13 Jun 2013 16:22:04 -0700 Subject: [PATCH] Parse nested namespaces in break point specifications. Changed the parser for break point specifications to allow nested namespace qualifiers. Also extended this to the exception command. --- hphp/runtime/debugger/break_point.cpp | 66 +++++--- hphp/runtime/debugger/cmd/cmd_exception.cpp | 2 +- hphp/test/quick/debugger/break2.php | 2 +- hphp/test/quick/debugger/break2.php.expectf | 2 +- hphp/test/quick/debugger/break3.php | 18 ++- hphp/test/quick/debugger/break3.php.expectf | 67 ++++++-- hphp/test/quick/debugger/break3.php.in | 22 ++- hphp/test/quick/debugger/exception1.php | 57 +++++++ .../quick/debugger/exception1.php.expectf | 151 ++++++++++++++++++ hphp/test/quick/debugger/exception1.php.in | 38 +++++ 10 files changed, 388 insertions(+), 37 deletions(-) create mode 100644 hphp/test/quick/debugger/exception1.php create mode 100644 hphp/test/quick/debugger/exception1.php.expectf create mode 100644 hphp/test/quick/debugger/exception1.php.in diff --git a/hphp/runtime/debugger/break_point.cpp b/hphp/runtime/debugger/break_point.cpp index ecf1e0eb9..8b5880748 100644 --- a/hphp/runtime/debugger/break_point.cpp +++ b/hphp/runtime/debugger/break_point.cpp @@ -671,8 +671,9 @@ void BreakPointInfo::parseBreakPointReached(const std::string &exp, if (offset2 == offset1) goto returnInvalid; name = exp.substr(offset1, offset2-offset1); } - if (offset1 < len && exp[offset1] == '\\') { - m_namespace = name; + while (offset1 < len && exp[offset1] == '\\') { + if (!m_namespace.empty()) m_namespace += "\\"; + m_namespace += name; offset1 += 1; auto offset2 = scanName(exp, offset1); // check for {namespace}\{something that is not a name} @@ -756,32 +757,57 @@ parseUrl: returnInvalid: m_valid = false; - return; } void BreakPointInfo::parseExceptionThrown(const std::string &exp) { TRACE(2, "BreakPointInfo::parseExceptionThrown\n"); - string input = exp; - // everything after @ is URL - size_t pos = input.find('@'); - if (pos != string::npos) { - m_url = input.substr(pos + 1); - input = input.substr(0, pos); + string name; + auto len = exp.length(); + auto offset0 = 0; + // Skip over a leading backslash + if (len > 0 && exp[0] == '\\') offset0++; + auto offset1 = scanName(exp, offset0); + // check that exp starts with a name + if (offset1 == offset0) goto returnInvalid; + name = exp.substr(offset0, offset1-offset0); + if (name.empty()) { + if (len > offset1 && exp[offset1] == '\\') offset1++; + auto offset2 = scanName(exp, offset1); + // check for {something other than a name} + if (offset2 == offset1) goto returnInvalid; + name = exp.substr(offset1, offset2-offset1); } - - pos = input.find("::"); - if (pos != string::npos) { - if (pos) { - m_namespace = input.substr(0, pos); - } - m_class = input.substr(pos + 2); + while (offset1 < len && exp[offset1] == '\\') { + if (!m_namespace.empty()) m_namespace += "\\"; + m_namespace += name; + offset1 += 1; + auto offset2 = scanName(exp, offset1); + // check for {namespace}\{something that is not a name} + if (offset2 == offset1) goto returnInvalid; + name = exp.substr(offset1, offset2-offset1); + offset1 = offset2; + } + m_class = name; + // Now we have a namespace and class name. + // The namespace might be empty. + mangleXhpName(m_class, m_class); + if (m_class == "error") m_class = ErrorClassName; + if (!m_namespace.empty()) { + m_class = m_namespace + "\\" + m_class; + m_namespace.clear(); + } + if (offset1 < len-2 && exp[offset1] == '@') { + offset1++; + m_url = exp.substr(offset1, len-offset1); } else { - m_class = input; - } - if (strncasecmp(m_class.c_str(), "error", m_class.size()) == 0) { - m_class = ErrorClassName; + // check for unparsed characters at end of exp + if (offset1 != len) goto returnInvalid; } + return; + +returnInvalid: + m_valid = false; } bool BreakPointInfo::MatchFile(const char *haystack, int haystack_len, diff --git a/hphp/runtime/debugger/cmd/cmd_exception.cpp b/hphp/runtime/debugger/cmd/cmd_exception.cpp index 47ec4fbf3..93bee2cf4 100644 --- a/hphp/runtime/debugger/cmd/cmd_exception.cpp +++ b/hphp/runtime/debugger/cmd/cmd_exception.cpp @@ -38,7 +38,7 @@ void CmdException::help(DebuggerClient &client) { client.helpTitle("Exception Command"); client.helpCmds( "[e]xception {cls}", "breaks if class of exception throws", - "[e]xception {ns}::{cls}", "breaks if class of exception throws", + "[e]xception {ns}\{cls}", "breaks if class of exception throws", "[e]xception error", "breaks on errors, warnings and notices", "[e]xception {above}@{url}", "breaks only if url also matches", "", "", diff --git a/hphp/test/quick/debugger/break2.php b/hphp/test/quick/debugger/break2.php index ad94fbbaa..d4a60b9cc 100644 --- a/hphp/test/quick/debugger/break2.php +++ b/hphp/test/quick/debugger/break2.php @@ -16,4 +16,4 @@ class cls2 { } } -error_log('break1.inc1 loaded'); +error_log('break2.php loaded'); diff --git a/hphp/test/quick/debugger/break2.php.expectf b/hphp/test/quick/debugger/break2.php.expectf index 4b72ed8ae..d36ccf528 100644 --- a/hphp/test/quick/debugger/break2.php.expectf +++ b/hphp/test/quick/debugger/break2.php.expectf @@ -8,7 +8,7 @@ Breakpoint 3 set upon entering cls2::pubObj() break cls2::pubCls() Breakpoint 4 set upon entering cls2::pubCls() run -break1.inc1 loaded +break2.php loaded Program %s/break2.php exited normally. @ foo2('test_break6') Breakpoint 2 reached at foo2() on line 6 of %s/break2.php diff --git a/hphp/test/quick/debugger/break3.php b/hphp/test/quick/debugger/break3.php index 4135ba8bd..8a65e1219 100644 --- a/hphp/test/quick/debugger/break3.php +++ b/hphp/test/quick/debugger/break3.php @@ -4,7 +4,7 @@ namespace TestNs; // Warning: line numbers are sensitive, do not change function foo($x) { - $y = $x.'_suffix'; + $y = $x.'_TestNs'; \error_log($y); } @@ -17,4 +17,20 @@ class cls { } } +namespace TestNs\Nested; + +function foo($x) { + $y = $x.'_TestNs\Nested'; + \error_log($y); +} + +class cls { + public function pubObj($x) { + \error_log("pubObj:".$x.'_TestNs\Nested'); + } + public static function pubCls($x) { + \error_log("pubCls:".$x.'_TestNs\Nested'); + } +} + \error_log('break3.php loaded'); diff --git a/hphp/test/quick/debugger/break3.php.expectf b/hphp/test/quick/debugger/break3.php.expectf index 80f5b9cbf..e370b8163 100644 --- a/hphp/test/quick/debugger/break3.php.expectf +++ b/hphp/test/quick/debugger/break3.php.expectf @@ -4,49 +4,96 @@ break3.php loaded Program %s/break3.php exited normally. break \TestNs\foo() Breakpoint 1 set upon entering TestNs\foo() -@ \TestNs\foo('test_break7') +@ \TestNs\foo('test_break1') Breakpoint 1 reached at TestNs\foo() on line 7 of %s/break3.php 6 function foo($x) { - 7 $y = $x.'_suffix'; + 7 $y = $x.'_TestNs'; 8 \error_log($y); variable -$x = "test_break7" +$x = "test_break1" break clear all All breakpoints are cleared. continue -test_break7_suffix +test_break1_TestNs break TestNs\cls::pubObj() Breakpoint 1 set upon entering TestNs\cls::pubObj() @ $break8=new \TestNs\cls() -@ $break8->pubObj('test_break8') +@ $break8->pubObj('test_break2') Breakpoint 1 reached at TestNs\cls::pubObj() on line 13 of %s/break3.php 12 public function pubObj($x) { 13 \error_log("pubObj:".$x); 14 } variable -$x = "test_break8" +$x = "test_break2" break clear all All breakpoints are cleared. continue -pubObj:test_break8 +pubObj:test_break2 break \TestNs\cls::pubCls() Breakpoint 1 set upon entering TestNs\cls::pubCls() -@ \TestNs\cls::pubCls('test_break9') +@ \TestNs\cls::pubCls('test_break3') Breakpoint 1 reached at TestNs\cls::pubCls() on line 16 of %s/break3.php 15 public static function pubCls($x) { 16 \error_log("pubCls:".$x); 17 } variable -$x = "test_break9" +$x = "test_break3" break clear all All breakpoints are cleared. continue -pubCls:test_break9 +pubCls:test_break3 + +break \TestNs\Nested\foo() +Breakpoint 1 set upon entering TestNs\Nested\foo() +@ \TestNs\Nested\foo('test_break4') +Breakpoint 1 reached at TestNs\Nested\foo() on line 23 of %s/break3.php + 22 function foo($x) { + 23 $y = $x.'_TestNs\Nested'; + 24 \error_log($y); + +variable +$x = "test_break4" +break clear all +All breakpoints are cleared. +continue +test_break4_TestNs\Nested + +break TestNs\Nested\cls::pubObj() +Breakpoint 1 set upon entering TestNs\Nested\cls::pubObj() +@ $break8=new \TestNs\Nested\cls() + +@ $break8->pubObj('test_break5') +Breakpoint 1 reached at TestNs\Nested\cls::pubObj() on line 29 of %s/break3.php + 28 public function pubObj($x) { + 29 \error_log("pubObj:".$x.'_TestNs\Nested'); + 30 } + +variable +$x = "test_break5" +break clear all +All breakpoints are cleared. +continue +pubObj:test_break5_TestNs\Nested + +break \TestNs\Nested\cls::pubCls() +Breakpoint 1 set upon entering TestNs\Nested\cls::pubCls() +@ \TestNs\Nested\cls::pubCls('test_break6') +Breakpoint 1 reached at TestNs\Nested\cls::pubCls() on line 32 of %s/break3.php + 31 public static function pubCls($x) { + 32 \error_log("pubCls:".$x.'_TestNs\Nested'); + 33 } + +variable +$x = "test_break6" +break clear all +All breakpoints are cleared. +continue +pubCls:test_break6_TestNs\Nested quit diff --git a/hphp/test/quick/debugger/break3.php.in b/hphp/test/quick/debugger/break3.php.in index 4bab06213..9ec453fb6 100644 --- a/hphp/test/quick/debugger/break3.php.in +++ b/hphp/test/quick/debugger/break3.php.in @@ -1,17 +1,33 @@ continue break \TestNs\foo() -@ \TestNs\foo('test_break7') +@ \TestNs\foo('test_break1') variable break clear all continue break TestNs\cls::pubObj() @ $break8=new \TestNs\cls() -@ $break8->pubObj('test_break8') +@ $break8->pubObj('test_break2') variable break clear all continue break \TestNs\cls::pubCls() -@ \TestNs\cls::pubCls('test_break9') +@ \TestNs\cls::pubCls('test_break3') +variable +break clear all +continue +break \TestNs\Nested\foo() +@ \TestNs\Nested\foo('test_break4') +variable +break clear all +continue +break TestNs\Nested\cls::pubObj() +@ $break8=new \TestNs\Nested\cls() +@ $break8->pubObj('test_break5') +variable +break clear all +continue +break \TestNs\Nested\cls::pubCls() +@ \TestNs\Nested\cls::pubCls('test_break6') variable break clear all continue diff --git a/hphp/test/quick/debugger/exception1.php b/hphp/test/quick/debugger/exception1.php new file mode 100644 index 000000000..cb56c40fa --- /dev/null +++ b/hphp/test/quick/debugger/exception1.php @@ -0,0 +1,57 @@ +