Skip to content

Commit fc1bcd6

Browse files
authored
psalm min v3.17 (#95)
* psalm min v3.17 * no message * no message
1 parent 1978eda commit fc1bcd6

File tree

8 files changed

+46
-36
lines changed

8 files changed

+46
-36
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"php": "^7.1",
1414
"ext-simplexml": "*",
1515
"symfony/framework-bundle": "^3.0 || ^4.0 || ^5.0",
16-
"vimeo/psalm": "^3.16 <3.17"
16+
"vimeo/psalm": "^3.17"
1717
},
1818
"require-dev": {
1919
"doctrine/orm": "^2.7",

psalm-baseline.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<files psalm-version="3.17.1@8f211792d813e4dc89f04ed372785ce93b902fd1">
3+
<file src="src/Twig/Context.php">
4+
<UnnecessaryVarAnnotation occurrences="2">
5+
<code>int</code>
6+
<code>string</code>
7+
</UnnecessaryVarAnnotation>
8+
</file>
9+
</files>

psalm.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
xmlns="https://getpsalm.org/schema/config"
66
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
77
cacheDirectory=".build/psalm"
8+
errorBaseline="psalm-baseline.xml"
89
>
910
<projectFiles>
1011
<directory name="src" />

src/Handler/ContainerHandler.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use Psalm\SymfonyPsalmPlugin\Symfony\ContainerMeta;
2222
use Psalm\Type\Atomic\TNamedObject;
2323
use Psalm\Type\Union;
24-
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
2524

2625
class ContainerHandler implements AfterMethodCallAnalysisInterface, AfterClassLikeVisitInterface
2726
{
@@ -105,7 +104,7 @@ public static function afterMethodCallAnalysis(
105104
}
106105

107106
if (!$service->isPublic()) {
108-
$isTestContainer = $context->parent && (KernelTestCase::class === $context->parent || is_subclass_of($context->parent, KernelTestCase::class));
107+
$isTestContainer = $context->parent && ('Symfony\Bundle\FrameworkBundle\Test\KernelTestCase' === $context->parent || is_subclass_of($context->parent, 'Symfony\Bundle\FrameworkBundle\Test\KernelTestCase'));
109108
if (!$isTestContainer) {
110109
IssueBuffer::accepts(
111110
new PrivateService($serviceId, new CodeLocation($statements_source, $expr->args[0]->value)),

src/Twig/AnalyzedTemplatesTainter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class AnalyzedTemplatesTainter implements AfterMethodCallAnalysisInterface
2424
public static function afterMethodCallAnalysis(Expr $expr, string $method_id, string $appearing_method_id, string $declaring_method_id, Context $context, StatementsSource $statements_source, Codebase $codebase, array &$file_replacements = [], Union &$return_type_candidate = null): void
2525
{
2626
if (
27-
null === $codebase->taint
27+
null === $codebase->taint_flow_graph
2828
|| !$expr instanceof MethodCall || $method_id !== Environment::class.'::render' || empty($expr->args)
2929
|| !isset($expr->args[0]->value) || !$expr->args[0]->value instanceof String_
3030
|| !isset($expr->args[1]->value) || !$expr->args[1]->value instanceof Array_
@@ -35,7 +35,7 @@ public static function afterMethodCallAnalysis(Expr $expr, string $method_id, st
3535
$template_name = $expr->args[0]->value->value;
3636
$twig_arguments_type = $statements_source->getNodeTypeProvider()->getType($expr->args[1]->value);
3737

38-
if (null === $twig_arguments_type || null === $twig_arguments_type->parent_nodes) {
38+
if (null === $twig_arguments_type) {
3939
return;
4040
}
4141

@@ -44,7 +44,7 @@ public static function afterMethodCallAnalysis(Expr $expr, string $method_id, st
4444
$sink_taint = TemplateFileAnalyzer::getTaintNodeForTwigNamedVariable(
4545
$template_name, $matches[1]
4646
);
47-
$codebase->taint->addPath($source_taint, $sink_taint, 'arg');
47+
$codebase->taint_flow_graph->addPath($source_taint, $sink_taint, 'arg');
4848
}
4949
}
5050
}

src/Twig/Context.php

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
namespace Psalm\SymfonyPsalmPlugin\Twig;
66

77
use Psalm\CodeLocation;
8-
use Psalm\Internal\Codebase\Taint;
9-
use Psalm\Internal\Taint\Sink;
10-
use Psalm\Internal\Taint\Taintable;
11-
use Psalm\Internal\Taint\TaintNode;
8+
use Psalm\Internal\Codebase\TaintFlowGraph;
9+
use Psalm\Internal\ControlFlow\ControlFlowNode;
10+
use Psalm\Internal\ControlFlow\TaintSink;
11+
use Psalm\Internal\ControlFlow\TaintSource;
1212
use Psalm\Type\TaintKind;
1313
use Twig\Node\Expression\FilterExpression;
1414
use Twig\Node\Expression\NameExpression;
@@ -18,25 +18,25 @@
1818

1919
class Context
2020
{
21-
/** @var array<string, Taintable> */
21+
/** @var array<string, ControlFlowNode> */
2222
private $unassignedVariables = [];
2323

24-
/** @var array<string, Taintable> */
24+
/** @var array<string, ControlFlowNode> */
2525
private $localVariables = [];
2626

2727
/** @var Source */
2828
private $sourceContext;
2929

30-
/** @var Taint */
30+
/** @var TaintFlowGraph */
3131
private $taint;
3232

33-
public function __construct(Source $sourceContext, Taint $taint)
33+
public function __construct(Source $sourceContext, TaintFlowGraph $taint)
3434
{
3535
$this->sourceContext = $sourceContext;
3636
$this->taint = $taint;
3737
}
3838

39-
public function addSink(Node $node, Taintable $source): void
39+
public function addSink(Node $node, ControlFlowNode $source): void
4040
{
4141
$codeLocation = $this->getNodeLocation($node);
4242

@@ -45,7 +45,7 @@ public function addSink(Node $node, Taintable $source): void
4545
$sinkName = 'twig_print';
4646
}
4747

48-
$sink = Sink::getForMethodArgument(
48+
$sink = TaintSink::getForMethodArgument(
4949
$sinkName, $sinkName, 0, null, $codeLocation
5050
);
5151

@@ -59,28 +59,28 @@ public function addSink(Node $node, Taintable $source): void
5959
$this->taint->addPath($source, $sink, 'arg');
6060
}
6161

62-
public function taintVariable(NameExpression $expression): Taintable
62+
public function taintVariable(NameExpression $expression): ControlFlowNode
6363
{
6464
/** @var string $variableName */
6565
$variableName = $expression->getAttribute('name');
6666

67-
$sinkNode = TaintNode::getForAssignment($variableName, $this->getNodeLocation($expression));
67+
$sinkNode = TaintSource::getForAssignment($variableName, $this->getNodeLocation($expression));
6868

69-
$this->taint->addTaintNode($sinkNode);
69+
$this->taint->addNode($sinkNode);
7070
$sinkNode = $this->addVariableTaintNode($expression);
7171

7272
return $this->addVariableUsage($variableName, $sinkNode);
7373
}
7474

75-
public function getTaintDestination(Taintable $taintSource, FilterExpression $expression): TaintNode
75+
public function getTaintDestination(ControlFlowNode $taintSource, FilterExpression $expression): ControlFlowNode
7676
{
7777
/** @var string $filterName */
7878
$filterName = $expression->getNode('filter')->getAttribute('value');
7979

8080
$returnLocation = $this->getNodeLocation($expression);
81-
$taintDestination = TaintNode::getForMethodReturn('filter_'.$filterName, 'filter_'.$filterName, $returnLocation, $returnLocation);
81+
$taintDestination = TaintSource::getForMethodReturn('filter_'.$filterName, 'filter_'.$filterName, $returnLocation, $returnLocation);
8282

83-
$this->taint->addTaintNode($taintDestination);
83+
$this->taint->addNode($taintDestination);
8484
$this->taint->addPath($taintSource, $taintDestination, 'arg');
8585

8686
return $taintDestination;
@@ -110,25 +110,25 @@ public function taintUnassignedVariables(string $templateName): void
110110
{
111111
foreach ($this->unassignedVariables as $variableName => $taintable) {
112112
$label = strtolower($templateName).'#'.strtolower($variableName);
113-
$taintSource = new TaintNode($label, $label, null, null);
113+
$taintSource = new TaintSource($label, $label, null, null);
114114

115-
$this->taint->addTaintNode($taintSource);
115+
$this->taint->addNode($taintSource);
116116
$this->taint->addPath($taintSource, $taintable, 'arg');
117117
}
118118
}
119119

120-
private function addVariableTaintNode(NameExpression $variableNode): TaintNode
120+
private function addVariableTaintNode(NameExpression $variableNode): ControlFlowNode
121121
{
122122
/** @var string $variableName */
123123
$variableName = $variableNode->getAttribute('name');
124-
$taintNode = TaintNode::getForAssignment($variableName, $this->getNodeLocation($variableNode));
124+
$taintNode = TaintSource::getForAssignment($variableName, $this->getNodeLocation($variableNode));
125125

126-
$this->taint->addTaintNode($taintNode);
126+
$this->taint->addNode($taintNode);
127127

128128
return $taintNode;
129129
}
130130

131-
private function addVariableUsage(string $variableName, Taintable $variableTaint): Taintable
131+
private function addVariableUsage(string $variableName, ControlFlowNode $variableTaint): ControlFlowNode
132132
{
133133
if (!isset($this->localVariables[$variableName])) {
134134
return $this->unassignedVariables[$variableName] = $variableTaint;
@@ -139,10 +139,12 @@ private function addVariableUsage(string $variableName, Taintable $variableTaint
139139

140140
private function getNodeLocation(Node $node): CodeLocation
141141
{
142+
/** @psalm-var string $fileName */
142143
$fileName = $this->sourceContext->getName();
143144
$filePath = $this->sourceContext->getPath();
144145
$snippet = $this->sourceContext->getCode(); // warning : the getCode method returns the whole template, not only the statement
145146
$fileCode = file_get_contents($filePath);
147+
/** @psalm-var int $lineNumber */
146148
$lineNumber = $node->getTemplateLine();
147149
$lines = explode("\n", $fileCode);
148150

src/Twig/PrintNodeAnalyzer.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Psalm\SymfonyPsalmPlugin\Twig;
66

7-
use Psalm\Internal\Taint\Taintable;
7+
use Psalm\Internal\ControlFlow\ControlFlowNode;
88
use RuntimeException;
99
use Twig\Node\Expression\AbstractExpression;
1010
use Twig\Node\Expression\FilterExpression;
@@ -47,7 +47,7 @@ private function expressionIsEscaped(AbstractExpression $expression): bool
4747
return false;
4848
}
4949

50-
private function getTaintSource(AbstractExpression $expression): ?Taintable
50+
private function getTaintSource(AbstractExpression $expression): ?ControlFlowNode
5151
{
5252
if ($expression instanceof FilterExpression) {
5353
/** @var AbstractExpression $filteredExpression */

src/Twig/TemplateFileAnalyzer.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Psalm\Context as PsalmContext;
88
use Psalm\Internal\Analyzer\FileAnalyzer;
9-
use Psalm\Internal\Taint\TaintNode;
9+
use Psalm\Internal\ControlFlow\TaintSource;
1010
use Twig\Environment;
1111
use Twig\Loader\FilesystemLoader;
1212
use Twig\NodeTraverser;
@@ -19,13 +19,12 @@ public function analyze(
1919
PsalmContext $global_context = null
2020
) {
2121
$codebase = $this->project_analyzer->getCodebase();
22+
$taint = $codebase->taint_flow_graph;
2223

23-
if (null === $codebase->taint) {
24+
if (null === $taint) {
2425
return;
2526
}
2627

27-
$taint = $codebase->taint;
28-
2928
$loader = new FilesystemLoader('templates', $codebase->config->base_dir);
3029
$twig = new Environment($loader, [
3130
'cache' => false,
@@ -53,9 +52,9 @@ public function analyze(
5352
public static function getTaintNodeForTwigNamedVariable(
5453
string $template_id,
5554
string $variable_name
56-
): TaintNode {
55+
): TaintSource {
5756
$label = $arg_id = strtolower($template_id).'#'.strtolower($variable_name);
5857

59-
return new TaintNode($arg_id, $label, null, null);
58+
return new TaintSource($arg_id, $label, null, null);
6059
}
6160
}

0 commit comments

Comments
 (0)