1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Remove TSqlSelectString and related dependency

This commit is contained in:
Matthew Brown 2019-05-20 23:14:41 -04:00
parent ea930b8875
commit a1eb191f57
10 changed files with 116 additions and 28 deletions

View File

@ -23,7 +23,6 @@
"symfony/console": "^3.3||^4.0",
"amphp/amp": "^2.1",
"amphp/byte-stream": "^1.5",
"phpmyadmin/sql-parser": "^5.0",
"sebastian/diff": "^3.0"
},
"bin": ["psalm", "psalter", "psalm-language-server", "psalm-plugin"],
@ -47,7 +46,8 @@
"phpunit/phpunit": "^7.5 || ^8.0",
"squizlabs/php_codesniffer": "3.4.0",
"bamarni/composer-bin-plugin": "^1.2",
"psalm/plugin-phpunit": "^0.6"
"psalm/plugin-phpunit": "^0.6",
"phpmyadmin/sql-parser": "^5.0"
},
"suggest": {
"ext-igbinary": "^2.0.5"

View File

@ -320,6 +320,13 @@ class Config
*/
public $after_statement_checks = [];
/**
* Static methods to be called after method checks have completed
*
* @var class-string<Hook\StringInterpreterInterface>[]
*/
public $string_interpreters = [];
/**
* Static methods to be called after classlike exists checks have completed
*

View File

@ -0,0 +1,13 @@
<?php
namespace Psalm\Plugin\Hook;
use Psalm\Type;
interface StringInterpreterInterface
{
/**
* Called after a statement has been checked
*/
public static function getTypeFromValue(string $value
) : ?Type\Atomic\TLiteralString;
}

View File

@ -112,5 +112,9 @@ class PluginRegistrationSocket implements RegistrationInterface
if (is_subclass_of($handler, Hook\AfterAnalysisInterface::class)) {
$this->config->after_analysis[$handler] = $handler;
}
if (is_subclass_of($handler, Hook\StringInterpreterInterface::class)) {
$this->config->string_interpreters[$handler] = $handler;
}
}
}

View File

@ -29,7 +29,6 @@ use Psalm\Type\Atomic\TObject;
use Psalm\Type\Atomic\TObjectWithProperties;
use Psalm\Type\Atomic\TResource;
use Psalm\Type\Atomic\TSingleLetter;
use Psalm\Type\Atomic\TSqlSelectString;
use Psalm\Type\Atomic\TString;
use Psalm\Type\Atomic\TTrue;
use Psalm\Type\Atomic\TVoid;
@ -933,16 +932,10 @@ abstract class Type
if ($value !== null) {
$config = \Psalm\Config::getInstance();
if ($config->parse_sql && stripos($value, 'select ') !== false) {
try {
$parser = new \PhpMyAdmin\SqlParser\Parser($value);
if (!$parser->errors) {
$type = new TSqlSelectString($value);
}
} catch (\Throwable $e) {
if (strlen($value) < $config->max_string_length) {
$type = new TLiteralString($value);
if ($config->string_interpreters) {
foreach ($config->string_interpreters as $string_interpreter) {
if ($type = $string_interpreter::getTypeFromValue($value)) {
break;
}
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace Psalm\Test\Config\Plugin\Hook;
use Psalm\Plugin\Hook\StringInterpreterInterface;
use Psalm\Type\Atomic\TLiteralString;
class SqlStringProvider implements StringInterpreterInterface
{
public static function getTypeFromValue(string $value) : ?TLiteralString
{
if (stripos($value, 'select ') !== false) {
try {
$parser = new \PhpMyAdmin\SqlParser\Parser($value);
if (!$parser->errors) {
return new StringProvider\TSqlSelectString($value);
}
} catch (\Throwable $e) {
// fall through
}
}
return null;
}
}

View File

@ -1,7 +1,8 @@
<?php
namespace Psalm\Type\Atomic;
class TSqlSelectString extends TLiteralString
namespace Psalm\Test\Config\Plugin\Hook\StringProvider;
class TSqlSelectString extends \Psalm\Type\Atomic\TLiteralString
{
/**
* @return string
@ -10,7 +11,6 @@ class TSqlSelectString extends TLiteralString
{
return 'sql-select-string';
}
/**
* @return string
*/
@ -18,7 +18,6 @@ class TSqlSelectString extends TLiteralString
{
return 'sql-select-string(' . $this->value . ')';
}
/**
* @return bool
*/

View File

@ -0,0 +1,18 @@
<?php
namespace Psalm\Test\Config\Plugin;
use Psalm\Plugin;
use SimpleXMLElement;
/** @psalm-suppress UnusedClass */
class SqlStringProviderPlugin implements \Psalm\Plugin\PluginEntryPointInterface
{
/** @return void */
public function __invoke(Plugin\RegistrationInterface $registration, SimpleXMLElement $config = null)
{
require_once __DIR__ . '/Hook/SqlStringProvider.php';
require_once __DIR__ . '/Hook/StringProvider/TSqlSelectString.php';
$registration->registerHooksFromClass(Hook\SqlStringProvider::class);
}
}

View File

@ -618,6 +618,46 @@ class PluginTest extends \Psalm\Tests\TestCase
$this->analyzeFile($file_path, new Context());
}
/** @return void */
public function testSqlStringProviderHooks()
{
require_once __DIR__ . '/Plugin/SqlStringProviderPlugin.php';
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__, 2) . DIRECTORY_SEPARATOR,
'<?xml version="1.0"?>
<psalm>
<projectFiles>
<directory name="src" />
</projectFiles>
<plugins>
<pluginClass class="Psalm\\Test\\Config\\Plugin\\SqlStringProviderPlugin" />
</plugins>
</psalm>'
)
);
$this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'<?php
$a = "select * from videos;";'
);
$context = new Context();
$this->analyzeFile($file_path, $context);
$this->assertTrue(isset($context->vars_in_scope['$a']));
foreach ($context->vars_in_scope['$a']->getTypes() as $type) {
$this->assertInstanceOf(\Psalm\Test\Config\Plugin\Hook\StringProvider\TSqlSelectString::class, $type);
}
}
/**
*
* @return void

View File

@ -486,17 +486,6 @@ class ValueTest extends TestCase
'assertions' => [],
'error_levels' => ['MissingParamType', 'MixedAssignment'],
],
'sqlTypes' => [
'<?php
$a = "select * from foo";
$b = "select * from";
$c = "select * from foo where i = :i";',
'assertions' => [
'$a===' => 'sql-select-string(select * from foo)',
'$b===' => 'string(select * from)',
'$c===' => 'sql-select-string(select * from foo where i = :i)',
],
],
'numericToStringComparison' => [
'<?php
/** @psalm-suppress MissingParamType */