diff --git a/src/difference/ArcanistDiffUtils.php b/src/difference/ArcanistDiffUtils.php
index a68a0532..0f798c9e 100644
--- a/src/difference/ArcanistDiffUtils.php
+++ b/src/difference/ArcanistDiffUtils.php
@@ -89,6 +89,9 @@ final class ArcanistDiffUtils extends Phobject {
$highlight_o = '';
$highlight_c = '';
+ $depth_in = '';
+ $depth_out = '';
+
$is_html = false;
if ($str instanceof PhutilSafeHTML) {
$is_html = true;
@@ -107,11 +110,23 @@ final class ArcanistDiffUtils extends Phobject {
$stack = array_shift($intra_stack);
$s = $e;
$e += $stack[1];
- } while ($stack[0] == 0);
+ } while ($stack[0] === 0);
+
+ switch ($stack[0]) {
+ case '>':
+ $open_tag = $depth_in;
+ break;
+ case '<':
+ $open_tag = $depth_out;
+ break;
+ default:
+ $open_tag = $highlight_o;
+ break;
+ }
}
if (!$highlight && !$tag && !$ent && $p == $s) {
- $buf .= $highlight_o;
+ $buf .= $open_tag;
$highlight = true;
}
@@ -139,7 +154,7 @@ final class ArcanistDiffUtils extends Phobject {
if ($tag && $str[$i] == '>') {
$tag = false;
if ($highlight) {
- $buf .= $highlight_o;
+ $buf .= $open_tag;
}
}
diff --git a/src/lint/linter/__tests__/jshint/jshint.lint-test b/src/lint/linter/__tests__/jshint/jshint.lint-test
index 37c13892..edb1c779 100644
--- a/src/lint/linter/__tests__/jshint/jshint.lint-test
+++ b/src/lint/linter/__tests__/jshint/jshint.lint-test
@@ -9,4 +9,4 @@ function f() {
~~~~~~~~~~
warning:3:8
error:7:1
-error:9:
+error:9:1
diff --git a/src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php
index b2fa6770..f3dd662e 100644
--- a/src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php
+++ b/src/lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php
@@ -26,6 +26,7 @@ final class ArcanistPHPCompatibilityXHPASTLinterRule
$whitelist = array(
'class' => array(),
'function' => array(),
+ 'constant' => array(),
);
$conditionals = $root->selectDescendantsOfType('n_IF');
@@ -51,6 +52,7 @@ final class ArcanistPHPCompatibilityXHPASTLinterRule
case 'class_exists':
case 'function_exists':
case 'interface_exists':
+ case 'defined':
$type = null;
switch ($function_name) {
case 'class_exists':
@@ -64,6 +66,10 @@ final class ArcanistPHPCompatibilityXHPASTLinterRule
case 'interface_exists':
$type = 'interface';
break;
+
+ case 'defined':
+ $type = 'constant';
+ break;
}
$params = $function->getChildOfType(1, 'n_CALL_PARAMETER_LIST');
@@ -98,7 +104,6 @@ final class ArcanistPHPCompatibilityXHPASTLinterRule
$min = idx($version, 'php.min');
$max = idx($version, 'php.max');
- // Check if whitelisted.
$whitelisted = false;
foreach (idx($whitelist['function'], $name, array()) as $range) {
if (array_intersect($range, array_keys($node->getTokens()))) {
@@ -178,18 +183,18 @@ final class ArcanistPHPCompatibilityXHPASTLinterRule
$version = idx($compat_info['classes'], $name, $version);
$min = idx($version, 'php.min');
$max = idx($version, 'php.max');
- // Check if whitelisted.
- $whitelisted = false;
- foreach (idx($whitelist['class'], $name, array()) as $range) {
- if (array_intersect($range, array_keys($node->getTokens()))) {
- $whitelisted = true;
- break;
- }
- }
- if ($whitelisted) {
- continue;
+ $whitelisted = false;
+ foreach (idx($whitelist['class'], $name, array()) as $range) {
+ if (array_intersect($range, array_keys($node->getTokens()))) {
+ $whitelisted = true;
+ break;
}
+ }
+
+ if ($whitelisted) {
+ continue;
+ }
if ($min && version_compare($min, $this->version, '>')) {
$this->raiseLintAtNode(
@@ -225,6 +230,18 @@ final class ArcanistPHPCompatibilityXHPASTLinterRule
$min = idx($version, 'php.min');
$max = idx($version, 'php.max');
+ $whitelisted = false;
+ foreach (idx($whitelist['constant'], $name, array()) as $range) {
+ if (array_intersect($range, array_keys($node->getTokens()))) {
+ $whitelisted = true;
+ break;
+ }
+ }
+
+ if ($whitelisted) {
+ continue;
+ }
+
if ($min && version_compare($min, $this->version, '>')) {
$this->raiseLintAtNode(
$node,
diff --git a/src/workflow/ArcanistDiffWorkflow.php b/src/workflow/ArcanistDiffWorkflow.php
index 28b91a3f..a427846b 100644
--- a/src/workflow/ArcanistDiffWorkflow.php
+++ b/src/workflow/ArcanistDiffWorkflow.php
@@ -1852,17 +1852,56 @@ EOTEXT
$this->checkRevisionOwnership(head($result));
break;
case 'reviewers':
- $untils = array();
+ $away = array();
foreach ($result as $user) {
- if (idx($user, 'currentStatus') == 'away') {
- $untils[] = $user['currentStatusUntil'];
+ if (idx($user, 'currentStatus') != 'away') {
+ continue;
}
+
+ $username = $user['userName'];
+ $real_name = $user['realName'];
+
+ if (strlen($real_name)) {
+ $name = pht('%s (%s)', $username, $real_name);
+ } else {
+ $name = pht('%s', $username);
+ }
+
+ $away[] = array(
+ 'name' => $name,
+ 'until' => $user['currentStatusUntil'],
+ );
}
- if (count($untils) == count($reviewers)) {
- $until = date('l, M j Y', min($untils));
- $confirm = pht(
- 'All reviewers are away until %s. Continue anyway?',
- $until);
+
+ if ($away) {
+ if (count($away) == count($reviewers)) {
+ $earliest_return = min(ipull($away, 'until'));
+
+ $message = pht(
+ 'All reviewers are away until %s:',
+ date('l, M j Y', $earliest_return));
+ } else {
+ $message = pht('Some reviewers are currently away:');
+ }
+
+ echo tsprintf(
+ "%s\n\n",
+ $message);
+
+ $list = id(new PhutilConsoleList());
+ foreach ($away as $spec) {
+ $list->addItem(
+ pht(
+ '%s (until %s)',
+ $spec['name'],
+ date('l, M j Y', $spec['until'])));
+ }
+
+ echo tsprintf(
+ '%B',
+ $list->drawConsoleString());
+
+ $confirm = pht('Continue even though reviewers are unavailable?');
if (!phutil_console_confirm($confirm)) {
throw new ArcanistUsageException(
pht('Specify available reviewers and retry.'));