Skip to content

Commit

Permalink
Merge pull request #15 from TysonAndre/fix-quadratic
Browse files Browse the repository at this point in the history
Fix quadratic runtime when file has multiple typos
  • Loading branch information
TysonAndre committed Oct 29, 2019
2 parents 3c47ac3 + 43c3353 commit 0cc64c8
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 11 deletions.
50 changes: 50 additions & 0 deletions src/LineCounter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php declare(strict_types=1);

namespace PhanTypoCheck;

class LineCounter
{
/** @var string the text used for counting lines */
private $line_counting_text;
/** @var int the length of the text */
private $length;
/** @var int the last checked byte offset. */
private $current_offset = 0;
/** @var int the 0-based line of the last checked offset */
private $current_line = 0;

/** @param array{0:int,1:string,2:int} $token the current token */
public function __construct(string $text, array $token)
{
if (\in_array($token[0], [\T_CONSTANT_ENCAPSED_STRING, \T_ENCAPSED_AND_WHITESPACE])) {
// Parse this, but replace `"\n"`, `"\x0a"`, etc. with a single byte character that isn't a literal newline.
$this->line_counting_text = StringUtil::parseWithNewlinePlaceholder($token[1]);
} else {
// There are no escape sequences
$this->line_counting_text = $text;
}
$this->length = strlen($this->line_counting_text);
}

/**
* @param int $offset - A 0-based byte offset
* @return int - gets the 1-based line number for $offset
*/
public function getLineNumberForOffset(int $offset) : int {
if ($offset < 0) {
$offset = 0;
} elseif ($offset > $this->length) {
$offset = $this->length;
}
$current_offset = $this->current_offset;
if ($offset > $current_offset) {
$this->current_line += \substr_count($this->line_counting_text, "\n", $current_offset, $offset - $current_offset);
$this->current_offset = $offset;
} elseif ($offset < $current_offset) {
$this->current_line -= \substr_count($this->line_counting_text, "\n", $offset, $current_offset - $offset);
$this->current_offset = $offset;
}
return $this->current_line;
}

}
17 changes: 6 additions & 11 deletions src/TypoCheckUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
use function stripos;
use function strtolower;
use function substr;
use function substr_count;
use function token_get_all;
use function trim;
use const PREG_OFFSET_CAPTURE;

require_once __DIR__ . '/LineCounter.php';
require_once __DIR__ . '/TypoDetails.php';
require_once __DIR__ . '/StringUtil.php';

Expand Down Expand Up @@ -86,20 +86,15 @@ public static function getTyposForText(string $contents, bool $plaintext = false

$analyze_text = static function (string $text, array $token) use ($dictionary, &$results) {
// @phan-suppress-next-line PhanUnusedVariableReference the reference is used to preserve state
$count_lines_before = static function (int $offset) use(&$line_counting_text, $text, $token) : int {
$count_lines_before = static function (int $offset) use($text, $token) : int {
if ($offset <= 0) {
return 0;
}
if (!isset($line_counting_text)) {
if (\in_array($token[0], [\T_CONSTANT_ENCAPSED_STRING, \T_ENCAPSED_AND_WHITESPACE])) {
// Parse this, but replace `"\n"`, `"\x0a"`, etc. with a single byte character that isn't a literal newline.
$line_counting_text = StringUtil::parseWithNewlinePlaceholder($token[1]);
} else {
// There are no escape sequences
$line_counting_text = $text;
}
static $line_counter;
if ($line_counter === null) {
$line_counter = new LineCounter($text, $token);
}
return substr_count($line_counting_text, "\n", 0, $offset);
return $line_counter->getLineNumberForOffset($offset);
};
preg_match_all('/[a-z0-9]{3,}(?:\'[a-z]+)?/i', $text, $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[0] as $match) {
Expand Down

0 comments on commit 0cc64c8

Please sign in to comment.