Changeset View
Changeset View
Standalone View
Standalone View
src/lint/linter/ArcanistSpellingLinter.php
Show First 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | switch ($key) { | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
return parent::setLinterConfigurationValue($key, $value); | return parent::setLinterConfigurationValue($key, $value); | ||||
} | } | ||||
public function loadDictionary($path) { | public function loadDictionary($path) { | ||||
$root = $this->getProjectRoot(); | // TOOLSETS: Restore the ability to reference resources relative to the | ||||
$path = Filesystem::resolvePath($path, $root); | // project root. | ||||
// $root = $this->getProjectRoot(); | |||||
// $path = Filesystem::resolvePath($path, $root); | |||||
$dict = phutil_json_decode(Filesystem::readFile($path)); | $dict = phutil_json_decode(Filesystem::readFile($path)); | ||||
PhutilTypeSpec::checkMap( | PhutilTypeSpec::checkMap( | ||||
$dict, | $dict, | ||||
array( | array( | ||||
'rules' => 'map<string, map<string, string>>', | 'rules' => 'map<string, map<string, string>>', | ||||
)); | )); | ||||
$rules = $dict['rules']; | $rules = $dict['rules']; | ||||
Show All 30 Lines | final class ArcanistSpellingLinter extends ArcanistLinter { | ||||
public function getLintNameMap() { | public function getLintNameMap() { | ||||
return array( | return array( | ||||
self::LINT_SPELLING_EXACT => pht('Possible Spelling Mistake'), | self::LINT_SPELLING_EXACT => pht('Possible Spelling Mistake'), | ||||
self::LINT_SPELLING_PARTIAL => pht('Possible Spelling Mistake'), | self::LINT_SPELLING_PARTIAL => pht('Possible Spelling Mistake'), | ||||
); | ); | ||||
} | } | ||||
public function lintPath($path) { | protected function lintPath(ArcanistWorkingCopyPath $path) { | ||||
// TODO: This is a bit hacky. If no dictionaries were specified, then add | // TODO: This is a bit hacky. If no dictionaries were specified, then add | ||||
// the default dictionary. | // the default dictionary. | ||||
if (!$this->dictionaries) { | if (!$this->dictionaries) { | ||||
$root = dirname(phutil_get_library_root('arcanist')); | $root = dirname(phutil_get_library_root('arcanist')); | ||||
$this->loadDictionary($root.'/resources/spelling/english.json'); | $this->loadDictionary($root.'/resources/spelling/english.json'); | ||||
} | } | ||||
foreach ($this->exactWordRules as $misspelling => $correction) { | foreach ($this->exactWordRules as $misspelling => $correction) { | ||||
$this->checkExactWord($path, $misspelling, $correction); | $this->checkExactWord($path, $misspelling, $correction); | ||||
} | } | ||||
foreach ($this->partialWordRules as $misspelling => $correction) { | foreach ($this->partialWordRules as $misspelling => $correction) { | ||||
$this->checkPartialWord($path, $misspelling, $correction); | $this->checkPartialWord($path, $misspelling, $correction); | ||||
} | } | ||||
} | } | ||||
private function checkExactWord($path, $word, $correction) { | private function checkExactWord( | ||||
$text = $this->getData($path); | ArcanistWorkingCopyPath $path, | ||||
$word, | |||||
$correction) { | |||||
$text = $path->getData(); | |||||
$matches = array(); | $matches = array(); | ||||
$num_matches = preg_match_all( | $num_matches = preg_match_all( | ||||
'#\b'.preg_quote($word, '#').'\b#i', | '#\b'.preg_quote($word, '#').'\b#i', | ||||
$text, | $text, | ||||
$matches, | $matches, | ||||
PREG_OFFSET_CAPTURE); | PREG_OFFSET_CAPTURE); | ||||
if (!$num_matches) { | if (!$num_matches) { | ||||
return; | return; | ||||
} | } | ||||
foreach ($matches[0] as $match) { | foreach ($matches[0] as $match) { | ||||
$original = $match[0]; | $original = $match[0]; | ||||
$replacement = self::fixLetterCase($correction, $original); | $replacement = self::fixLetterCase($correction, $original); | ||||
$this->raiseLintAtOffset( | $this->raiseLintAtOffset( | ||||
$match[1], | $match[1], | ||||
self::LINT_SPELLING_EXACT, | self::LINT_SPELLING_EXACT, | ||||
pht( | pht( | ||||
"Possible spelling error. You wrote '%s', but did you mean '%s'?", | "Possible spelling error. You wrote '%s', but did you mean '%s'?", | ||||
$word, | $word, | ||||
$correction), | $correction), | ||||
$original, | $original, | ||||
$replacement); | $replacement); | ||||
} | } | ||||
} | } | ||||
private function checkPartialWord($path, $word, $correction) { | private function checkPartialWord( | ||||
$text = $this->getData($path); | ArcanistWorkingCopyPath $path, | ||||
$word, | |||||
$correction) { | |||||
$text = $path->getData(); | |||||
$pos = 0; | $pos = 0; | ||||
while ($pos < strlen($text)) { | while ($pos < strlen($text)) { | ||||
$next = stripos($text, $word, $pos); | $next = stripos($text, $word, $pos); | ||||
if ($next === false) { | if ($next === false) { | ||||
return; | return; | ||||
} | } | ||||
$original = substr($text, $next, strlen($word)); | $original = substr($text, $next, strlen($word)); | ||||
$replacement = self::fixLetterCase($correction, $original); | $replacement = self::fixLetterCase($correction, $original); | ||||
Show All 27 Lines |