Skip to content

Commit

Permalink
Fix linter annotations for special editors
Browse files Browse the repository at this point in the history
When the sql string to lint isa changed, the result positions
need to be adjusted accordingly.

Signed-off-by: Maximilian Krög <maxi_kroeg@web.de>
  • Loading branch information
MoonE committed Apr 21, 2024
1 parent 02ebd6c commit 3abe6fe
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 63 deletions.
3 changes: 1 addition & 2 deletions js/src/database/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,7 @@ const DatabaseEvents = {
* the Definition textarea.
*/
var $elm = $('textarea[name=item_definition]').last();
var linterOptions = {};
linterOptions.eventEditor = true;
var linterOptions = { editorType: 'event' };
that.syntaxHiglighter = Functions.getSqlEditor($elm, {}, 'both', linterOptions);
} else {
Functions.ajaxShowMessage(data.error, false);
Expand Down
3 changes: 1 addition & 2 deletions js/src/database/routines.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,7 @@ const DatabaseRoutines = {
* the Definition textarea.
*/
var $elm = $('textarea[name=item_definition]').last();
var linterOptions = {};
linterOptions.routineEditor = true;
var linterOptions = { editorType: 'routine' };
that.syntaxHiglighter = Functions.getSqlEditor($elm, {}, 'both', linterOptions);

// Execute item-specific code
Expand Down
3 changes: 1 addition & 2 deletions js/src/database/triggers.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,7 @@ const DatabaseTriggers = {
* the Definition textarea.
*/
var $elm = $('textarea[name=item_definition]').last();
var linterOptions = {};
linterOptions.triggerEditor = true;
var linterOptions = { editorType: 'trigger' };
that.syntaxHiglighter = Functions.getSqlEditor($elm, {}, 'both', linterOptions);
} else {
Functions.ajaxShowMessage(data.error, false);
Expand Down
53 changes: 30 additions & 23 deletions libraries/classes/Controllers/LintController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,52 +10,59 @@
use PhpMyAdmin\Core;
use PhpMyAdmin\Linter;

use function is_array;
use function is_string;
use function json_encode;

/**
* Represents the interface between the linter and the query editor.
*/
class LintController extends AbstractController
{
public const EDITOR_SQL_PREFIX = [
'event' => "DELIMITER $$ CREATE EVENT `a` ON SCHEDULE EVERY MINUTE DO\n",
'routine' => "DELIMITER $$ CREATE PROCEDURE `a`()\n",
'trigger' => "DELIMITER $$ CREATE TRIGGER `a` AFTER INSERT ON `b` FOR EACH ROW\n",
];

public function __invoke(): void
{
$params = [
'sql_query' => $_POST['sql_query'] ?? null,
'options' => $_POST['options'] ?? null,
];
$sqlQueryParam = $_POST['sql_query'] ?? null;
$options = $_POST['options'] ?? null;

/**
* The SQL query to be analyzed.
*
* This does not need to be checked again XSS or MySQL injections because it is
* This does not need to be checked against XSS or MySQL injections because it is
* never executed, just parsed.
*
* The client, which will receive the JSON response will decode the message and
* and any HTML fragments that are displayed to the user will be encoded anyway.
*
* @var string
*/
$sqlQuery = ! empty($params['sql_query']) ? $params['sql_query'] : '';
$sqlQuery = is_string($sqlQueryParam) ? $sqlQueryParam : '';

$this->response->setAjax(true);
$editorType = is_array($options) ? ($options['editorType'] ?? null) : null;
$prefix = is_string($editorType) ? self::EDITOR_SQL_PREFIX[$editorType] ?? '' : '';

// Disabling standard response.
$this->response->disable();

Core::headerJSON();
$lints = Linter::lint($prefix . $sqlQuery);
if ($prefix !== '') {
// Adjust positions to account for prefix
foreach ($lints as &$lint) {
if ($lint['fromLine'] === 0) {
continue;
}

if (! empty($params['options'])) {
$options = $params['options'];

if (! empty($options['routineEditor'])) {
$sqlQuery = "DELIMITER $$\nCREATE PROCEDURE `a`() " . $sqlQuery;
} elseif (! empty($options['triggerEditor'])) {
$sqlQuery = "DELIMITER $$\nCREATE TRIGGER `a` AFTER INSERT ON `b` FOR EACH ROW " . $sqlQuery;
} elseif (! empty($options['eventEditor'])) {
$sqlQuery = "DELIMITER $$\nCREATE EVENT `a` ON SCHEDULE EVERY MINUTE DO " . $sqlQuery;
$lint['fromLine'] -= 1;
$lint['toLine'] -= 1;
}

unset($lint);
}

echo json_encode(Linter::lint($sqlQuery));
$this->response->setAjax(true);
// Disabling standard response.
$this->response->disable();
Core::headerJSON();
echo json_encode($lints);
}
}
15 changes: 12 additions & 3 deletions libraries/classes/Linter.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class Linter
*
* @param string|UtfString $str String to be analyzed.
*
* @return array
* @return array<int,int>
* @psalm-return list<int>
*/
public static function getLines($str)
{
Expand Down Expand Up @@ -72,8 +73,10 @@ public static function getLines($str)
*
* @param array $lines The starting position of each line.
* @param int $pos The absolute position
* @psalm-param list<int> $lines
*
* @return array
* @psalm-return array{int, int}
*/
public static function findLineNumberAndColumn(array $lines, $pos)
{
Expand All @@ -98,6 +101,14 @@ public static function findLineNumberAndColumn(array $lines, $pos)
* @param string $query The query to be checked.
*
* @return array
* @psalm-return list<array{
* message: string,
* fromLine: int,
* fromColumn: int,
* toLine: int,
* toColumn: int,
* severity: string,
* }>
*/
public static function lint($query)
{
Expand Down Expand Up @@ -132,8 +143,6 @@ public static function lint($query)

/**
* The response containing of all errors.
*
* @var array
*/
$response = [];

Expand Down
25 changes: 0 additions & 25 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5185,31 +5185,6 @@ parameters:
count: 1
path: libraries/classes/Linter.php

-
message: "#^Method PhpMyAdmin\\\\Linter\\:\\:findLineNumberAndColumn\\(\\) has parameter \\$lines with no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Linter.php

-
message: "#^Method PhpMyAdmin\\\\Linter\\:\\:findLineNumberAndColumn\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Linter.php

-
message: "#^Method PhpMyAdmin\\\\Linter\\:\\:getLines\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Linter.php

-
message: "#^Method PhpMyAdmin\\\\Linter\\:\\:lint\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Linter.php

-
message: "#^PHPDoc tag @var has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Linter.php

-
message: "#^Parameter \\#2 \\$pos of static method PhpMyAdmin\\\\Linter\\:\\:findLineNumberAndColumn\\(\\) expects int, int\\|string\\|null given\\.$#"
count: 1
Expand Down
6 changes: 0 additions & 6 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8355,12 +8355,6 @@
<InvalidScalarArgument occurrences="1">
<code>$error[3]</code>
</InvalidScalarArgument>
<MixedAssignment occurrences="1">
<code>$lineStart</code>
</MixedAssignment>
<MixedOperand occurrences="1">
<code>$lines[$line]</code>
</MixedOperand>
<PossiblyInvalidOperand occurrences="1">
<code>$error[3]</code>
</PossiblyInvalidOperand>
Expand Down

0 comments on commit 3abe6fe

Please sign in to comment.