Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/4.x' into upstream-master
Browse files Browse the repository at this point in the history
  • Loading branch information
orklah committed Jan 14, 2022
2 parents 9ac77e9 + cdbaf0e commit b633619
Show file tree
Hide file tree
Showing 33 changed files with 982 additions and 405 deletions.
25 changes: 25 additions & 0 deletions bin/generate_issues_list_doc.php
@@ -0,0 +1,25 @@
#!/usr/bin/env php
<?php

$docs_dir = dirname(__DIR__) . DIRECTORY_SEPARATOR . "docs"
. DIRECTORY_SEPARATOR . "running_psalm" . DIRECTORY_SEPARATOR;
$issues_index = "{$docs_dir}issues.md";
$issues_dir = "{$docs_dir}issues";

if (!file_exists($issues_dir)) {
throw new UnexpectedValueException("Issues documentation not found");
}

$issues_list = array_filter(array_map(function (string $issue_file) {
if ($issue_file === "." || $issue_file === ".." || substr($issue_file, -3) !== ".md") {
return false;
}

$issue = substr($issue_file, 0, strlen($issue_file) - 3);
return " - [$issue](issues/$issue.md)";
}, scandir($issues_dir)));

usort($issues_list, "strcasecmp");

$issues_md_contents = array_merge(["# Issue types", ""], $issues_list, [""]);
file_put_contents($issues_index, implode("\n", $issues_md_contents));
9 changes: 8 additions & 1 deletion config.xsd
Expand Up @@ -41,7 +41,13 @@
<xs:attribute name="findUnusedCode" type="xs:boolean" default="false" />
<xs:attribute name="findUnusedVariablesAndParams" type="xs:boolean" default="false" />
<xs:attribute name="findUnusedPsalmSuppress" type="xs:boolean" default="false" />
<xs:attribute name="forbidEcho" type="xs:boolean" default="false" />
<xs:attribute name="forbidEcho" type="xs:boolean" default="false">
<xs:annotation>
<xs:documentation xml:lang="en">
Deprecated. Will be replaced by adding echo to forbiddenFunctions in Psalm 5.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="hideExternalErrors" type="xs:boolean" default="false" />
<xs:attribute name="hoistConstants" type="xs:boolean" default="false" />
<xs:attribute name="ignoreInternalFunctionFalseReturn" type="xs:boolean" default="true" />
Expand Down Expand Up @@ -69,6 +75,7 @@
<xs:attribute name="usePhpDocPropertiesWithoutMagicCall" type="xs:boolean" default="false" />
<xs:attribute name="skipChecksOnUnresolvableIncludes" type="xs:boolean" default="false" />
<xs:attribute name="sealAllMethods" type="xs:boolean" default="false" />
<xs:attribute name="sealAllProperties" type="xs:boolean" default="false" />
<xs:attribute name="runTaintAnalysis" type="xs:boolean" default="false" />
<xs:attribute name="usePhpStormMetaPath" type="xs:boolean" default="true" />
<xs:attribute name="allowInternalNamedArgumentCalls" type="xs:boolean" default="true" />
Expand Down
2 changes: 1 addition & 1 deletion dictionaries/CallMap.php
Expand Up @@ -1996,7 +1996,7 @@
'dio_tcsetattr' => ['bool', 'fd'=>'resource', 'options'=>'array'],
'dio_truncate' => ['bool', 'fd'=>'resource', 'offset'=>'int'],
'dio_write' => ['int', 'fd'=>'resource', 'data'=>'string', 'length='=>'int'],
'dir' => ['Directory|false|null', 'directory'=>'string', 'context='=>'resource'],
'dir' => ['Directory|false', 'directory'=>'string', 'context='=>'resource'],
'Directory::close' => ['void', 'dir_handle='=>'resource'],
'Directory::read' => ['string|false', 'dir_handle='=>'resource'],
'Directory::rewind' => ['void', 'dir_handle='=>'resource'],
Expand Down
2 changes: 1 addition & 1 deletion dictionaries/CallMap_historical.php
Expand Up @@ -10375,7 +10375,7 @@
'dio_tcsetattr' => ['bool', 'fd'=>'resource', 'options'=>'array'],
'dio_truncate' => ['bool', 'fd'=>'resource', 'offset'=>'int'],
'dio_write' => ['int', 'fd'=>'resource', 'data'=>'string', 'length='=>'int'],
'dir' => ['Directory|false|null', 'directory'=>'string', 'context='=>'resource'],
'dir' => ['Directory|false', 'directory'=>'string', 'context='=>'resource'],
'dirname' => ['string', 'path'=>'string', 'levels='=>'int'],
'disk_free_space' => ['float|false', 'directory'=>'string'],
'disk_total_space' => ['float|false', 'directory'=>'string'],
Expand Down
10 changes: 10 additions & 0 deletions docs/running_psalm/configuration.md
Expand Up @@ -294,6 +294,16 @@ This defaults to `false`.

When `true`, Psalm will treat all classes as if they had sealed methods, meaning that if you implement the magic method `__call`, you also have to add `@method` for each magic method. Defaults to false.

#### sealAllProperties

```xml
<psalm
sealAllProperties="[bool]"
>
```

When `true`, Psalm will treat all classes as if they had sealed properties, meaning that Psalm will disallow getting and setting any properties not contained in a list of `@property` (or `@property-read`/`@property-write`) annotations and not explicitly defined as a `property`. Defaults to false.

#### runTaintAnalysis

```xml
Expand Down
11 changes: 11 additions & 0 deletions docs/running_psalm/issues.md
Expand Up @@ -7,6 +7,7 @@
- [CircularReference](issues/CircularReference.md)
- [ComplexFunction](issues/ComplexFunction.md)
- [ComplexMethod](issues/ComplexMethod.md)
- [ConfigIssue](issues/ConfigIssue.md)
- [ConflictingReferenceConstraint](issues/ConflictingReferenceConstraint.md)
- [ConstructorSignatureMismatch](issues/ConstructorSignatureMismatch.md)
- [ContinueOutsideLoop](issues/ContinueOutsideLoop.md)
Expand All @@ -21,6 +22,8 @@
- [DuplicateArrayKey](issues/DuplicateArrayKey.md)
- [DuplicateClass](issues/DuplicateClass.md)
- [DuplicateConstant](issues/DuplicateConstant.md)
- [DuplicateEnumCase](issues/DuplicateEnumCase.md)
- [DuplicateEnumCaseValue](issues/DuplicateEnumCaseValue.md)
- [DuplicateFunction](issues/DuplicateFunction.md)
- [DuplicateMethod](issues/DuplicateMethod.md)
- [DuplicateParam](issues/DuplicateParam.md)
Expand Down Expand Up @@ -62,6 +65,7 @@
- [InvalidDocblock](issues/InvalidDocblock.md)
- [InvalidDocblockParamName](issues/InvalidDocblockParamName.md)
- [InvalidEnumBackingType](issues/InvalidEnumBackingType.md)
- [InvalidEnumCaseValue](issues/InvalidEnumCaseValue.md)
- [InvalidExtendClass](issues/InvalidExtendClass.md)
- [InvalidFalsableReturnType](issues/InvalidFalsableReturnType.md)
- [InvalidFunctionCall](issues/InvalidFunctionCall.md)
Expand Down Expand Up @@ -132,6 +136,7 @@
- [MoreSpecificReturnType](issues/MoreSpecificReturnType.md)
- [MutableDependency](issues/MutableDependency.md)
- [NamedArgumentNotAllowed](issues/NamedArgumentNotAllowed.md)
- [NoEnumProperties](issues/NoEnumProperties.md)
- [NoInterfaceProperties](issues/NoInterfaceProperties.md)
- [NonInvariantDocblockPropertyType](issues/NonInvariantDocblockPropertyType.md)
- [NonInvariantPropertyType](issues/NonInvariantPropertyType.md)
Expand Down Expand Up @@ -166,6 +171,7 @@
- [PossiblyInvalidArrayOffset](issues/PossiblyInvalidArrayOffset.md)
- [PossiblyInvalidCast](issues/PossiblyInvalidCast.md)
- [PossiblyInvalidClone](issues/PossiblyInvalidClone.md)
- [PossiblyInvalidDocblockTag](issues/PossiblyInvalidDocblockTag.md)
- [PossiblyInvalidFunctionCall](issues/PossiblyInvalidFunctionCall.md)
- [PossiblyInvalidIterator](issues/PossiblyInvalidIterator.md)
- [PossiblyInvalidMethodCall](issues/PossiblyInvalidMethodCall.md)
Expand Down Expand Up @@ -193,6 +199,7 @@
- [PossiblyUnusedMethod](issues/PossiblyUnusedMethod.md)
- [PossiblyUnusedParam](issues/PossiblyUnusedParam.md)
- [PossiblyUnusedProperty](issues/PossiblyUnusedProperty.md)
- [PossiblyUnusedReturnValue](issues/PossiblyUnusedReturnValue.md)
- [PropertyNotSetInConstructor](issues/PropertyNotSetInConstructor.md)
- [PropertyTypeCoercion](issues/PropertyTypeCoercion.md)
- [RawObjectIteration](issues/RawObjectIteration.md)
Expand Down Expand Up @@ -221,6 +228,7 @@
- [TaintedSql](issues/TaintedSql.md)
- [TaintedSSRF](issues/TaintedSSRF.md)
- [TaintedSystemSecret](issues/TaintedSystemSecret.md)
- [TaintedTextWithQuotes](issues/TaintedTextWithQuotes.md)
- [TaintedUnserialize](issues/TaintedUnserialize.md)
- [TaintedUserSecret](issues/TaintedUserSecret.md)
- [TooFewArguments](issues/TooFewArguments.md)
Expand Down Expand Up @@ -259,14 +267,17 @@
- [UnrecognizedExpression](issues/UnrecognizedExpression.md)
- [UnrecognizedStatement](issues/UnrecognizedStatement.md)
- [UnresolvableInclude](issues/UnresolvableInclude.md)
- [UnsafeGenericInstantiation](issues/UnsafeGenericInstantiation.md)
- [UnsafeInstantiation](issues/UnsafeInstantiation.md)
- [UnusedClass](issues/UnusedClass.md)
- [UnusedClosureParam](issues/UnusedClosureParam.md)
- [UnusedConstructor](issues/UnusedConstructor.md)
- [UnusedForeachValue](issues/UnusedForeachValue.md)
- [UnusedFunctionCall](issues/UnusedFunctionCall.md)
- [UnusedMethod](issues/UnusedMethod.md)
- [UnusedMethodCall](issues/UnusedMethodCall.md)
- [UnusedParam](issues/UnusedParam.md)
- [UnusedProperty](issues/UnusedProperty.md)
- [UnusedPsalmSuppress](issues/UnusedPsalmSuppress.md)
- [UnusedReturnValue](issues/UnusedReturnValue.md)
- [UnusedVariable](issues/UnusedVariable.md)
3 changes: 3 additions & 0 deletions docs/running_psalm/issues/ComplexFunction.md
@@ -0,0 +1,3 @@
# ComplexFunction

Emitted when a function is too complicated. Complicated functions should be split up.
3 changes: 3 additions & 0 deletions docs/running_psalm/issues/ComplexMethod.md
@@ -0,0 +1,3 @@
# ComplexMethod

Emitted when a method is too complicated. Complicated methods should be split up.
2 changes: 1 addition & 1 deletion docs/running_psalm/issues/ForbiddenEcho.md
@@ -1,7 +1,7 @@
# ForbiddenEcho

Emitted when Psalm encounters an echo statement and the `forbidEcho` flag in your config is set to `true`

This issue is deprecated and will be removed in Psalm 5. Adding echo to forbiddenFunctions in config will result in ForbiddenCode issue instead
```php
<?php

Expand Down
38 changes: 23 additions & 15 deletions src/Psalm/Config.php
Expand Up @@ -344,6 +344,11 @@ class Config
*/
public $seal_all_methods = false;

/**
* @var bool
*/
public $seal_all_properties = false;

/**
* @var bool
*/
Expand Down Expand Up @@ -910,6 +915,7 @@ private static function fromXmlAndPaths(
'reportMixedIssues' => 'show_mixed_issues',
'skipChecksOnUnresolvableIncludes' => 'skip_checks_on_unresolvable_includes',
'sealAllMethods' => 'seal_all_methods',
'sealAllProperties' => 'seal_all_properties',
'runTaintAnalysis' => 'run_taint_analysis',
'usePhpStormMetaPath' => 'use_phpstorm_meta_path',
'allowInternalNamedArgumentsCalls' => 'allow_internal_named_arg_calls',
Expand Down Expand Up @@ -1180,21 +1186,23 @@ private static function fromXmlAndPaths(
}

if (isset($config_xml->issueHandlers)) {
/** @var SimpleXMLElement $issue_handler */
foreach ($config_xml->issueHandlers->children() as $key => $issue_handler) {
if ($key === 'PluginIssue') {
$custom_class_name = (string) $issue_handler['name'];
/** @var string $key */
$config->issue_handlers[$custom_class_name] = IssueHandler::loadFromXMLElement(
$issue_handler,
$base_dir
);
} else {
/** @var string $key */
$config->issue_handlers[$key] = IssueHandler::loadFromXMLElement(
$issue_handler,
$base_dir
);
foreach ($config_xml->issueHandlers as $issue_handlers) {
/** @var SimpleXMLElement $issue_handler */
foreach ($issue_handlers->children() as $key => $issue_handler) {
if ($key === 'PluginIssue') {
$custom_class_name = (string) $issue_handler['name'];
/** @var string $key */
$config->issue_handlers[$custom_class_name] = IssueHandler::loadFromXMLElement(
$issue_handler,
$base_dir
);
} else {
/** @var string $key */
$config->issue_handlers[$key] = IssueHandler::loadFromXMLElement(
$issue_handler,
$base_dir
);
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/Psalm/Internal/Analyzer/ClassAnalyzer.php
Expand Up @@ -1938,6 +1938,7 @@ public static function analyzeClassMethodReturnType(
$method_analyzer,
$interface_return_type,
$interface_class,
$original_fq_classlike_name,
$interface_return_type_location,
[$analyzed_method_id->__toString()],
$did_explicitly_return
Expand All @@ -1963,6 +1964,7 @@ public static function analyzeClassMethodReturnType(
$method_analyzer,
$return_type,
$fq_classlike_name,
$original_fq_classlike_name,
$return_type_location,
$overridden_method_ids,
$did_explicitly_return
Expand Down
Expand Up @@ -80,6 +80,7 @@ public static function verifyReturnType(
FunctionLikeAnalyzer $function_like_analyzer,
?Union $return_type = null,
?string $fq_class_name = null,
?string $static_fq_class_name = null,
?CodeLocation $return_type_location = null,
array $compatible_method_ids = [],
bool $did_explicitly_return = false,
Expand Down Expand Up @@ -421,7 +422,7 @@ public static function verifyReturnType(
$codebase,
$return_type,
$self_fq_class_name,
$self_fq_class_name,
$static_fq_class_name,
$parent_class,
true,
true,
Expand Down
7 changes: 7 additions & 0 deletions src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php
Expand Up @@ -464,6 +464,12 @@ public function analyze(
$this->track_mutations = true;
}

if ($this->function instanceof ArrowFunction && $storage->return_type && $storage->return_type->isNever()) {
// ArrowFunction perform a return implicitly so if the return type is never, we have to suppress the error
// note: the never can only come from phpdoc. PHP will refuse short closures with never in signature
$statements_analyzer->addSuppressedIssues(['NoValue']);
}

$statements_analyzer->analyze($function_stmts, $context, $global_context, true);

if ($codebase->alter_code
Expand Down Expand Up @@ -1413,6 +1419,7 @@ public function verifyReturnType(
$this,
$return_type,
$fq_class_name,
$fq_class_name,
$return_type_location,
[],
$did_explicitly_return,
Expand Down
10 changes: 10 additions & 0 deletions src/Psalm/Internal/Analyzer/ScopeAnalyzer.php
Expand Up @@ -91,6 +91,16 @@ public static function getControlActions(
($stmt instanceof PhpParser\Node\Stmt\Expression && $stmt->expr instanceof PhpParser\Node\Expr\Exit_)
) {
if (!$return_is_exit && $stmt instanceof PhpParser\Node\Stmt\Return_) {
$stmt_return_type = null;
if ($nodes && $stmt->expr) {
$stmt_return_type = $nodes->getType($stmt->expr);
}

// don't consider a return if the expression never returns (e.g. a throw inside a short closure)
if ($stmt_return_type && ($stmt_return_type->isNever() || $stmt_return_type->isEmpty())) {
return array_values(array_unique(array_merge($control_actions, [self::ACTION_END])));
}

return array_values(array_unique(array_merge($control_actions, [self::ACTION_RETURN])));
}

Expand Down

0 comments on commit b633619

Please sign in to comment.