Index: src/__phutil_library_map__.php =================================================================== --- src/__phutil_library_map__.php +++ src/__phutil_library_map__.php @@ -885,6 +885,8 @@ 'ManiphestCreateMailReceiver' => 'applications/maniphest/mail/ManiphestCreateMailReceiver.php', 'ManiphestCustomField' => 'applications/maniphest/field/ManiphestCustomField.php', 'ManiphestCustomFieldNumericIndex' => 'applications/maniphest/storage/ManiphestCustomFieldNumericIndex.php', + 'ManiphestCustomFieldStatusParser' => 'applications/maniphest/field/parser/ManiphestCustomFieldStatusParser.php', + 'ManiphestCustomFieldStatusParserTestCase' => 'applications/maniphest/field/parser/__tests__/ManiphestCustomFieldStatusParserTestCase.php', 'ManiphestCustomFieldStorage' => 'applications/maniphest/storage/ManiphestCustomFieldStorage.php', 'ManiphestCustomFieldStringIndex' => 'applications/maniphest/storage/ManiphestCustomFieldStringIndex.php', 'ManiphestDAO' => 'applications/maniphest/storage/ManiphestDAO.php', @@ -3498,6 +3500,8 @@ 'ManiphestCreateMailReceiver' => 'PhabricatorMailReceiver', 'ManiphestCustomField' => 'PhabricatorCustomField', 'ManiphestCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', + 'ManiphestCustomFieldStatusParser' => 'PhabricatorCustomFieldMonogramParser', + 'ManiphestCustomFieldStatusParserTestCase' => 'PhabricatorTestCase', 'ManiphestCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'ManiphestCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 'ManiphestDAO' => 'PhabricatorLiskDAO', Index: src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php =================================================================== --- src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php +++ src/applications/differential/field/specification/DifferentialFreeformFieldSpecification.php @@ -44,53 +44,36 @@ '' => null, ); - $prefix_regex = array(); - foreach ($prefixes as $prefix => $resolution) { - $prefix_regex[] = preg_quote($prefix, '/'); - } - $prefix_regex = implode('|', $prefix_regex); - - $suffix_regex = array(); - foreach ($suffixes as $suffix => $resolution) { - $suffix_regex[] = preg_quote($suffix, '/'); - } - $suffix_regex = implode('|', $suffix_regex); - - $matches = null; - preg_match_all( - "/({$prefix_regex})\s+T(\d+)\s*({$suffix_regex})/i", - $message, - $matches, - PREG_SET_ORDER); + $matches = id(new ManiphestCustomFieldStatusParser()) + ->parseCorpus($message); - $tasks_statuses = array(); - foreach ($matches as $set) { - $prefix = strtolower($set[1]); - $task_id = (int)$set[2]; - $suffix = strtolower($set[3]); + $task_statuses = array(); + foreach ($matches as $match) { + $prefix = phutil_utf8_strtolower($match['prefix']); + $suffix = phutil_utf8_strtolower($match['suffix']); $status = idx($suffixes, $suffix); if (!$status) { $status = idx($prefixes, $prefix); } - $tasks_statuses[$task_id] = $status; + foreach ($match['monograms'] as $task_monogram) { + $task_id = (int)trim($task_monogram, 'tT'); + $task_statuses[$task_id] = $status; + } } - return $tasks_statuses; + return $task_statuses; } private function findDependentRevisions($message) { - $dependents = array(); + $matches = id(new DifferentialCustomFieldDependsOnParser()) + ->parseCorpus($message); - $matches = null; - preg_match_all( - '/\b(?i:depends\s+on):?\s+D(\d+(,\s+D\d++)*)\b/', - $message, - $matches); - - foreach ($matches[1] as $revisions) { - foreach (preg_split('/,\s+D/', $revisions) as $id) { + $dependents = array(); + foreach ($matches as $match) { + foreach ($match['monograms'] as $monogram) { + $id = (int)trim($monogram, 'dD'); $dependents[$id] = $id; } } @@ -99,46 +82,13 @@ } public static function findRevertedCommits($message) { - $reverts = array(); - $matches = null; - - // NOTE: Git language is "This reverts commit X." - // NOTE: Mercurial language is "Backed out changeset Y". - - $prefixes = array( - 'revert' => true, - 'reverts' => true, - 'back\s*out' => true, - 'backs\s*out' => true, - 'backed\s*out' => true, - 'undo' => true, - 'undoes' => true, - ); - - $optional = array( - 'commit' => true, - 'changeset' => true, - 'rev' => true, - 'revision' => true, - 'change' => true, - 'diff' => true, - ); - - $pre_re = implode('|', array_keys($prefixes)); - $opt_re = implode('|', array_keys($optional)); - - $matches = null; - preg_match_all( - '/\b(?i:'.$pre_re.')(?:\s+(?i:'.$opt_re.'))?([rA-Z0-9a-f,\s]+)\b/', - $message, - $matches); + $matches = id(new DifferentialCustomFieldRevertsParser()) + ->parseCorpus($message); $result = array(); - foreach ($matches[1] as $commits) { - $commits = preg_split('/[,\s]+/', $commits); - $commits = array_filter($commits); - foreach ($commits as $commit) { - $result[$commit] = $commit; + foreach ($matches as $match) { + foreach ($match['monograms'] as $monogram) { + $result[$monogram] = $monogram; } } Index: src/applications/maniphest/field/parser/ManiphestCustomFieldStatusParser.php =================================================================== --- /dev/null +++ src/applications/maniphest/field/parser/ManiphestCustomFieldStatusParser.php @@ -0,0 +1,59 @@ + array(), + 'T123' => array(), + 'Fixes T123' => array( + array( + 'match' => 'Fixes T123', + 'prefix' => 'Fixes', + 'infix' => '', + 'monograms' => array('T123'), + 'suffix' => '', + 'offset' => 0, + ), + ), + 'Fixes T123, T124, and also some other bugs.' => array( + array( + 'match' => 'Fixes T123, T124, ', + 'prefix' => 'Fixes', + 'infix' => '', + 'monograms' => array('T123', 'T124'), + 'suffix' => '', + 'offset' => 0, + ), + ), + 'Closes T1 as wontfix' => array( + array( + 'match' => 'Closes T1 as wontfix', + 'prefix' => 'Closes', + 'infix' => '', + 'monograms' => array('T1'), + 'suffix' => 'as wontfix', + 'offset' => 0, + ), + ), + 'Fixes task T9' => array( + array( + 'match' => 'Fixes task T9', + 'prefix' => 'Fixes', + 'infix' => 'task', + 'monograms' => array('T9'), + 'suffix' => '', + 'offset' => 0, + ), + ), + 'Fixes t2apps' => array(), + 'fixes a bug' => array(), + 'Prefixes T2' => array(), + ); + + foreach ($map as $input => $expect) { + $parser = new ManiphestCustomFieldStatusParser(); + $output = $parser->parseCorpus($input); + + $this->assertEqual($expect, $output, $input); + } + } + +} Index: src/infrastructure/customfield/parser/PhabricatorCustomFieldMonogramParser.php =================================================================== --- src/infrastructure/customfield/parser/PhabricatorCustomFieldMonogramParser.php +++ src/infrastructure/customfield/parser/PhabricatorCustomFieldMonogramParser.php @@ -47,7 +47,7 @@ 'prefix' => $set[1][0], 'infix' => $set[2][0], 'monograms' => array_filter(preg_split('/[,\s]+/', $set[3][0])), - 'suffix' => $set[4][0], + 'suffix' => idx(idx($set, 4, array()), 0, ''), 'offset' => $set[0][1], ); }