diff options
author | Dan Ungureanu <udan1107@gmail.com> | 2015-07-13 20:22:30 +0300 |
---|---|---|
committer | Dan Ungureanu <udan1107@gmail.com> | 2015-07-15 16:48:13 +0300 |
commit | eef994f122121253e2bea856f7259b2a4578bc64 (patch) | |
tree | c3dadccc588c16ea6e3b4347b60cbf11c8976c88 /lint.php | |
parent | ea015a53890954837f2207734224ec3134a8e5d6 (diff) |
Added lint.
Signed-off-by: Dan Ungureanu <udan1107@gmail.com>
Diffstat (limited to 'lint.php')
-rw-r--r-- | lint.php | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/lint.php b/lint.php new file mode 100644 index 0000000000..d434de81b2 --- /dev/null +++ b/lint.php @@ -0,0 +1,137 @@ +<?php + +// Loads the SQL lexer and parser, which are used to parse this error to detect +// any errors. +require_once 'libraries/sql-parser/autoload.php'; + +/** + * Gets the starting position of each line. + * + * @param string $str String to be analyzed. + * + * @return array + */ +function getLines($str) +{ + $lines = array(0); + for ($i = 0, $len = strlen($str); $i < $len; ++$i) { + if ($str[$i] === "\n") { + $lines[] = $i; + } + } + return $lines; +} + +/** + * Computes the number of the line and column given an absolute position. + * + * @param array $lines The starting position of each line. + * @param int $pos The absolute position + * + * @return void + */ +function findLineNumberAndColumn($lines, $pos) +{ + $line = 0; + foreach ($lines as $lineNo => $lineStart) { + if ($lineStart >= $pos) { + break; + } + $line = $lineNo; + } + return array($line, $pos - $lines[$line]); +} + +/** + * Runs the linting process. + * + * @param string $query The query to be checked. + * + * @return void + */ +function linter($query) +{ + // Disabling lint for huge queries to save some resources. + if (strlen($query) > 10000) { + echo json_encode( + array( + array( + 'message' => 'The linting is disabled for this query because it exceededs the maxmimum length', + 'fromLine' => 0, + 'fromColumn' => 0, + 'toLine' => 0, + 'toColumn' => 0, + 'severity' => 'warning', + ) + ) + ); + return; + } + + /** + * Lexer used for tokenizing the query. + * + * @var SqlParser\Lexer + */ + $lexer = new SqlParser\Lexer($query); + + /** + * Parsed used for analysing the query. + * + * @var SqlParser\Parser + */ + $parser = new SqlParser\Parser($lexer->list); + + /** + * Array containing all errors. + * + * @var array + */ + $errors = SqlParser\Utils\Error::get(array($lexer, $parser)); + + /** + * The response containing of all errors. + * + * @var array + */ + $response = array(); + + /** + * The starting position for each line. + * + * CodeMirror requires relative position to line, but the parser stores + * only the absolute position of the character in string. + * + * @var array + */ + $lines = getLines($query); + + // Building the response. + foreach ($errors as $idx => $error) { + + // Starting position of the string that caused the error. + list($fromLine, $fromColumn) = findLineNumberAndColumn( + $lines, $error[3] + ); + + // Ending position of the string that caused the error. + list($toLine, $toColumn) = findLineNumberAndColumn( + $lines, $error[3] + strlen($error[2]) + ); + + // Building the response. + $response[] = array( + 'message' => $error[0] . ' (near ' . $error[2] . ')', + 'fromLine' => $fromLine, + 'fromColumn' => $fromColumn, + 'toLine' => $toLine, + 'toColumn' => $toColumn, + 'severity' => 'error', + ); + } + + // Sending back the answer. + echo json_encode($response); +} + +linter($_REQUEST['sql_query']); |