Skip to content

Commit

Permalink
Support Psalm v4.0 (#98)
Browse files Browse the repository at this point in the history
* Support Psalm v4.0

* no message

* no message

* no message
  • Loading branch information
seferov authored Oct 20, 2020
1 parent 720e554 commit 6c6b4f5
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 32 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/integrate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
restore-keys: php-${{ matrix.php-version }}-psalm-

- name: "Run vimeo/psalm"
run: vendor/bin/psalm --find-dead-code --find-unused-psalm-suppress --diff --diff-methods --shepherd --show-info=false --stats --output-format=github
run: vendor/bin/psalm --find-dead-code --find-unused-psalm-suppress --shepherd --show-info=false --stats --output-format=github

tests:
name: "Tests"
Expand All @@ -71,10 +71,9 @@ jobs:
strategy:
matrix:
php-version:
- 7.1
- 7.2
- 7.3
- 7.4
- nightly

symfony-version:
- 3
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
}
],
"require": {
"php": "^7.1",
"php": "^7.3 || ^8.0",
"ext-simplexml": "*",
"symfony/framework-bundle": "^3.0 || ^4.0 || ^5.0",
"vimeo/psalm": "^3.17"
"vimeo/psalm": "^4.0"
},
"require-dev": {
"doctrine/orm": "^2.7",
Expand Down
2 changes: 1 addition & 1 deletion src/Handler/ConsoleHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static function afterMethodCallAnalysis(
Codebase $codebase,
array &$file_replacements = [],
Union &$return_type_candidate = null
) {
): void {
switch ($declaring_method_id) {
case 'Symfony\Component\Console\Command\Command::addargument':
self::analyseArgument($expr->args, $statements_source);
Expand Down
4 changes: 3 additions & 1 deletion src/Handler/ContainerDependencyHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static function afterStatementAnalysis(
StatementsSource $statements_source,
Codebase $codebase,
array &$file_replacements = []
) {
): ?bool {
if ($stmt instanceof Node\Stmt\ClassMethod && '__construct' === $stmt->name->name) {
foreach ($stmt->params as $param) {
if ($param->type instanceof Node\Name && ContainerInterface::class === $param->type->getAttribute('resolvedName')) {
Expand All @@ -34,5 +34,7 @@ public static function afterStatementAnalysis(
}
}
}

return null;
}
}
2 changes: 1 addition & 1 deletion src/Handler/ContainerHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static function afterMethodCallAnalysis(
Codebase $codebase,
array &$file_replacements = [],
Union &$return_type_candidate = null
) {
): void {
if (!self::isContainerMethod($declaring_method_id, 'get')) {
if (self::isContainerMethod($declaring_method_id, 'getparameter')) {
$argument = $expr->args[0]->value;
Expand Down
2 changes: 1 addition & 1 deletion src/Handler/DoctrineRepositoryHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static function afterMethodCallAnalysis(
Codebase $codebase,
array &$file_replacements = [],
Union &$return_type_candidate = null
) {
): void {
if (in_array($declaring_method_id, ['Doctrine\ORM\EntityManagerInterface::getrepository', 'Doctrine\Persistence\ObjectManager::getrepository'])) {
$entityName = $expr->args[0]->value;
if ($entityName instanceof String_) {
Expand Down
14 changes: 12 additions & 2 deletions src/Handler/HeaderBagHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Psalm\Context;
use Psalm\Plugin\Hook\MethodReturnTypeProviderInterface;
use Psalm\StatementsSource;
use Psalm\Type;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TNull;
Expand All @@ -25,8 +26,17 @@ public static function getClassLikeNames(): array
];
}

public static function getMethodReturnType(StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, array $call_args, Context $context, CodeLocation $code_location, array $template_type_parameters = null, string $called_fq_classlike_name = null, string $called_method_name_lowercase = null)
{
public static function getMethodReturnType(
StatementsSource $source,
string $fq_classlike_name,
string $method_name_lowercase,
array $call_args,
Context $context,
CodeLocation $code_location,
?array $template_type_parameters = null,
?string $called_fq_classlike_name = null,
?string $called_method_name_lowercase = null
): ?Type\Union {
if (HeaderBag::class !== $fq_classlike_name) {
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ protected function getStubsForMajorVersion(int $majorVersion): array
/**
* {@inheritdoc}
*/
public function __invoke(RegistrationInterface $api, SimpleXMLElement $config = null)
public function __invoke(RegistrationInterface $api, SimpleXMLElement $config = null): void
{
require_once __DIR__.'/Handler/HeaderBagHandler.php';
require_once __DIR__.'/Handler/ContainerHandler.php';
Expand Down
19 changes: 15 additions & 4 deletions src/Twig/CachedTemplatesTainter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,23 @@ public static function getClassLikeNames(): array
return [Environment::class];
}

public static function getMethodReturnType(StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, array $call_args, Context $context, CodeLocation $code_location, array $template_type_parameters = null, string $called_fq_classlike_name = null, string $called_method_name_lowercase = null): void
{
public static function getMethodReturnType(
StatementsSource $source,
string $fq_classlike_name,
string $method_name_lowercase,
array $call_args,
Context $context,
CodeLocation $code_location,
?array $template_type_parameters = null,
?string $called_fq_classlike_name = null,
?string $called_method_name_lowercase = null
): ?Union {
if (!$source instanceof StatementsAnalyzer) {
throw new RuntimeException(sprintf('The %s::%s hook can only be called using a %s.', __CLASS__, __METHOD__, StatementsAnalyzer::class));
}

if ('render' !== $method_name_lowercase) {
return;
return null;
}

$fake_method_call = new MethodCall(
Expand All @@ -52,7 +61,7 @@ public static function getMethodReturnType(StatementsSource $source, string $fq_

$firstArgument = $call_args[0]->value;
if (!$firstArgument instanceof String_) {
return;
return null;
}

$cacheClassName = CachedTemplatesMapping::getCacheClassName($firstArgument->value);
Expand All @@ -66,5 +75,7 @@ public static function getMethodReturnType(StatementsSource $source, string $fq_
$fake_method_call,
$context
);

return null;
}
}
20 changes: 10 additions & 10 deletions src/Twig/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

use Psalm\CodeLocation;
use Psalm\Internal\Codebase\TaintFlowGraph;
use Psalm\Internal\ControlFlow\ControlFlowNode;
use Psalm\Internal\ControlFlow\TaintSink;
use Psalm\Internal\ControlFlow\TaintSource;
use Psalm\Internal\DataFlow\DataFlowNode;
use Psalm\Internal\DataFlow\TaintSink;
use Psalm\Internal\DataFlow\TaintSource;
use Psalm\Type\TaintKind;
use Twig\Node\Expression\FilterExpression;
use Twig\Node\Expression\NameExpression;
Expand All @@ -18,10 +18,10 @@

class Context
{
/** @var array<string, ControlFlowNode> */
/** @var array<string, DataFlowNode> */
private $unassignedVariables = [];

/** @var array<string, ControlFlowNode> */
/** @var array<string, DataFlowNode> */
private $localVariables = [];

/** @var Source */
Expand All @@ -36,7 +36,7 @@ public function __construct(Source $sourceContext, TaintFlowGraph $taint)
$this->taint = $taint;
}

public function addSink(Node $node, ControlFlowNode $source): void
public function addSink(Node $node, DataFlowNode $source): void
{
$codeLocation = $this->getNodeLocation($node);

Expand All @@ -59,7 +59,7 @@ public function addSink(Node $node, ControlFlowNode $source): void
$this->taint->addPath($source, $sink, 'arg');
}

public function taintVariable(NameExpression $expression): ControlFlowNode
public function taintVariable(NameExpression $expression): DataFlowNode
{
/** @var string $variableName */
$variableName = $expression->getAttribute('name');
Expand All @@ -72,7 +72,7 @@ public function taintVariable(NameExpression $expression): ControlFlowNode
return $this->addVariableUsage($variableName, $sinkNode);
}

public function getTaintDestination(ControlFlowNode $taintSource, FilterExpression $expression): ControlFlowNode
public function getTaintDestination(DataFlowNode $taintSource, FilterExpression $expression): DataFlowNode
{
/** @var string $filterName */
$filterName = $expression->getNode('filter')->getAttribute('value');
Expand Down Expand Up @@ -117,7 +117,7 @@ public function taintUnassignedVariables(string $templateName): void
}
}

private function addVariableTaintNode(NameExpression $variableNode): ControlFlowNode
private function addVariableTaintNode(NameExpression $variableNode): DataFlowNode
{
/** @var string $variableName */
$variableName = $variableNode->getAttribute('name');
Expand All @@ -128,7 +128,7 @@ private function addVariableTaintNode(NameExpression $variableNode): ControlFlow
return $taintNode;
}

private function addVariableUsage(string $variableName, ControlFlowNode $variableTaint): ControlFlowNode
private function addVariableUsage(string $variableName, DataFlowNode $variableTaint): DataFlowNode
{
if (!isset($this->localVariables[$variableName])) {
return $this->unassignedVariables[$variableName] = $variableTaint;
Expand Down
4 changes: 2 additions & 2 deletions src/Twig/PrintNodeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Psalm\SymfonyPsalmPlugin\Twig;

use Psalm\Internal\ControlFlow\ControlFlowNode;
use Psalm\Internal\DataFlow\DataFlowNode;
use RuntimeException;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\FilterExpression;
Expand Down Expand Up @@ -47,7 +47,7 @@ private function expressionIsEscaped(AbstractExpression $expression): bool
return false;
}

private function getTaintSource(AbstractExpression $expression): ?ControlFlowNode
private function getTaintSource(AbstractExpression $expression): ?DataFlowNode
{
if ($expression instanceof FilterExpression) {
/** @var AbstractExpression $filteredExpression */
Expand Down
8 changes: 4 additions & 4 deletions src/Twig/TemplateFileAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Psalm\Context as PsalmContext;
use Psalm\Internal\Analyzer\FileAnalyzer;
use Psalm\Internal\ControlFlow\TaintSource;
use Psalm\Internal\DataFlow\DataFlowNode;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Twig\NodeTraverser;
Expand All @@ -17,7 +17,7 @@ public function analyze(
PsalmContext $file_context = null,
bool $preserve_analyzers = false,
PsalmContext $global_context = null
) {
): void {
$codebase = $this->project_analyzer->getCodebase();
$taint = $codebase->taint_flow_graph;

Expand Down Expand Up @@ -52,9 +52,9 @@ public function analyze(
public static function getTaintNodeForTwigNamedVariable(
string $template_id,
string $variable_name
): TaintSource {
): DataFlowNode {
$label = $arg_id = strtolower($template_id).'#'.strtolower($variable_name);

return new TaintSource($arg_id, $label, null, null);
return new DataFlowNode($arg_id, $label, null, null);
}
}

0 comments on commit 6c6b4f5

Please sign in to comment.