mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Fix #3032 - always replay docblock issues when analysing files
This commit is contained in:
parent
86a89b2d27
commit
93735712f0
@ -208,6 +208,10 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($storage->docblock_issues as $docblock_issue) {
|
||||||
|
IssueBuffer::add($docblock_issue);
|
||||||
|
}
|
||||||
|
|
||||||
$classlike_storage_provider = $codebase->classlike_storage_provider;
|
$classlike_storage_provider = $codebase->classlike_storage_provider;
|
||||||
|
|
||||||
$parent_fq_class_name = $this->parent_fq_class_name;
|
$parent_fq_class_name = $this->parent_fq_class_name;
|
||||||
|
@ -180,6 +180,10 @@ class FileAnalyzer extends SourceAnalyzer implements StatementsSource
|
|||||||
$this->node_data = new \Psalm\Internal\Provider\NodeDataProvider();
|
$this->node_data = new \Psalm\Internal\Provider\NodeDataProvider();
|
||||||
$statements_analyzer = new StatementsAnalyzer($this, $this->node_data);
|
$statements_analyzer = new StatementsAnalyzer($this, $this->node_data);
|
||||||
|
|
||||||
|
foreach ($file_storage->docblock_issues as $docblock_issue) {
|
||||||
|
IssueBuffer::add($docblock_issue);
|
||||||
|
}
|
||||||
|
|
||||||
// if there are any leftover statements, evaluate them,
|
// if there are any leftover statements, evaluate them,
|
||||||
// in turn causing the classes/interfaces be evaluated
|
// in turn causing the classes/interfaces be evaluated
|
||||||
if ($leftover_stmts) {
|
if ($leftover_stmts) {
|
||||||
|
@ -158,6 +158,10 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($storage->docblock_issues as $docblock_issue) {
|
||||||
|
IssueBuffer::add($docblock_issue);
|
||||||
|
}
|
||||||
|
|
||||||
$overridden_method_ids = [];
|
$overridden_method_ids = [];
|
||||||
|
|
||||||
if ($this->function instanceof ClassMethod) {
|
if ($this->function instanceof ClassMethod) {
|
||||||
|
@ -172,27 +172,15 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
$this->type_aliases += $type_alias_tokens;
|
$this->type_aliases += $type_alias_tokens;
|
||||||
} catch (DocblockParseException $e) {
|
} catch (DocblockParseException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$this->file_storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
(string)$e->getMessage(),
|
||||||
(string)$e->getMessage(),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->file_storage->has_docblock_issues = true;
|
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$this->file_storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
(string)$e->getMessage(),
|
||||||
(string)$e->getMessage(),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->file_storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,15 +422,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|| isset($comments['specials']['template-implements'])
|
|| isset($comments['specials']['template-implements'])
|
||||||
|| isset($comments['specials']['implements'])
|
|| isset($comments['specials']['implements'])
|
||||||
) {
|
) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'You must use @use or @template-use to parameterize traits',
|
||||||
'You must use @use or @template-use to parameterize traits',
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($node instanceof PhpParser\Node\Expr\Include_) {
|
} elseif ($node instanceof PhpParser\Node\Expr\Include_) {
|
||||||
@ -664,10 +647,6 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$this->file_storage->has_visitor_issues = true;
|
$this->file_storage->has_visitor_issues = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($classlike_storage->has_docblock_issues) {
|
|
||||||
$this->file_storage->has_docblock_issues = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($node->name) {
|
if ($node->name) {
|
||||||
$this->class_template_types = [];
|
$this->class_template_types = [];
|
||||||
}
|
}
|
||||||
@ -715,10 +694,6 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
if ($functionlike_storage->has_visitor_issues) {
|
if ($functionlike_storage->has_visitor_issues) {
|
||||||
$this->file_storage->has_visitor_issues = true;
|
$this->file_storage->has_visitor_issues = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($functionlike_storage->has_docblock_issues) {
|
|
||||||
$this->file_storage->has_docblock_issues = true;
|
|
||||||
}
|
|
||||||
} elseif ($node instanceof PhpParser\Node\Stmt\If_ && $node->getLine() === $this->skip_if_descendants) {
|
} elseif ($node instanceof PhpParser\Node\Stmt\If_ && $node->getLine() === $this->skip_if_descendants) {
|
||||||
$this->exists_cond_expr = null;
|
$this->exists_cond_expr = null;
|
||||||
$this->not_exists_cond_expr = null;
|
$this->not_exists_cond_expr = null;
|
||||||
@ -1136,15 +1111,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$this->aliases
|
$this->aliases
|
||||||
);
|
);
|
||||||
} catch (DocblockParseException $e) {
|
} catch (DocblockParseException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
||||||
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
$name_location ?: $class_location
|
||||||
$name_location ?: $class_location
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($docblock_info) {
|
if ($docblock_info) {
|
||||||
@ -1173,16 +1143,12 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for '
|
||||||
$e->getMessage() . ' in docblock for '
|
. implode('.', $this->fq_classlike_names),
|
||||||
. implode('.', $this->fq_classlike_names),
|
$name_location ?: $class_location
|
||||||
$name_location ?: $class_location
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,15 +1156,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$fq_classlike_name => [$template_type],
|
$fq_classlike_name => [$template_type],
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Template missing as type',
|
||||||
'Template missing as type',
|
$name_location ?: $class_location
|
||||||
$name_location ?: $class_location
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/** @psalm-suppress PropertyTypeCoercion due to a Psalm bug */
|
/** @psalm-suppress PropertyTypeCoercion due to a Psalm bug */
|
||||||
@ -1248,15 +1209,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$storage->pseudo_property_get_types[$property['name']] = $pseudo_property_type;
|
$storage->pseudo_property_get_types[$property['name']] = $pseudo_property_type;
|
||||||
}
|
}
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
||||||
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
$name_location ?: $class_location
|
||||||
$name_location ?: $class_location
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1282,15 +1238,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
if ($docblock_info->mixin) {
|
if ($docblock_info->mixin) {
|
||||||
if (isset($this->class_template_types[$docblock_info->mixin])) {
|
if (isset($this->class_template_types[$docblock_info->mixin])) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Templates are not currently supported for @mixin',
|
||||||
'Templates are not currently supported for @mixin',
|
$name_location ?: $class_location
|
||||||
$name_location ?: $class_location
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
} else {
|
} else {
|
||||||
$storage->mixin_fqcln = Type::getFQCLNFromString(
|
$storage->mixin_fqcln = Type::getFQCLNFromString(
|
||||||
$docblock_info->mixin,
|
$docblock_info->mixin,
|
||||||
@ -1335,15 +1286,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
string $extended_class_name
|
string $extended_class_name
|
||||||
) {
|
) {
|
||||||
if (trim($extended_class_name) === '') {
|
if (trim($extended_class_name) === '') {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Extended class cannot be empty in docblock for ' . implode('.', $this->fq_classlike_names),
|
||||||
'Extended class cannot be empty in docblock for ' . implode('.', $this->fq_classlike_names),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1360,29 +1306,19 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$this->class_template_types
|
$this->class_template_types
|
||||||
);
|
);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
||||||
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$extended_union_type->isSingle()) {
|
if (!$extended_union_type->isSingle()) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-extends cannot be a union type',
|
||||||
'@template-extends cannot be a union type',
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$extended_union_type->setFromDocblock();
|
$extended_union_type->setFromDocblock();
|
||||||
@ -1395,15 +1331,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
foreach ($extended_union_type->getAtomicTypes() as $atomic_type) {
|
foreach ($extended_union_type->getAtomicTypes() as $atomic_type) {
|
||||||
if (!$atomic_type instanceof Type\Atomic\TGenericObject) {
|
if (!$atomic_type instanceof Type\Atomic\TGenericObject) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-extends has invalid class ' . $atomic_type->getId(),
|
||||||
'@template-extends has invalid class ' . $atomic_type->getId(),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1413,16 +1344,11 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
if (!isset($storage->parent_classes[$generic_class_lc])
|
if (!isset($storage->parent_classes[$generic_class_lc])
|
||||||
&& !isset($storage->parent_interfaces[$generic_class_lc])
|
&& !isset($storage->parent_interfaces[$generic_class_lc])
|
||||||
) {
|
) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-extends must include the name of an extended class,'
|
||||||
'@template-extends must include the name of an extended class,'
|
. ' got ' . $atomic_type->getId(),
|
||||||
. ' got ' . $atomic_type->getId(),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$extended_type_parameters = [];
|
$extended_type_parameters = [];
|
||||||
@ -1446,15 +1372,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
string $implemented_class_name
|
string $implemented_class_name
|
||||||
) {
|
) {
|
||||||
if (trim($implemented_class_name) === '') {
|
if (trim($implemented_class_name) === '') {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Extended class cannot be empty in docblock for ' . implode('.', $this->fq_classlike_names),
|
||||||
'Extended class cannot be empty in docblock for ' . implode('.', $this->fq_classlike_names),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1471,29 +1392,19 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$this->class_template_types
|
$this->class_template_types
|
||||||
);
|
);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
||||||
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$implemented_union_type->isSingle()) {
|
if (!$implemented_union_type->isSingle()) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-implements cannot be a union type',
|
||||||
'@template-implements cannot be a union type',
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1508,15 +1419,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
foreach ($implemented_union_type->getAtomicTypes() as $atomic_type) {
|
foreach ($implemented_union_type->getAtomicTypes() as $atomic_type) {
|
||||||
if (!$atomic_type instanceof Type\Atomic\TGenericObject) {
|
if (!$atomic_type instanceof Type\Atomic\TGenericObject) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-implements has invalid class ' . $atomic_type->getId(),
|
||||||
'@template-implements has invalid class ' . $atomic_type->getId(),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1524,16 +1430,11 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$generic_class_lc = strtolower($atomic_type->value);
|
$generic_class_lc = strtolower($atomic_type->value);
|
||||||
|
|
||||||
if (!isset($storage->class_implements[$generic_class_lc])) {
|
if (!isset($storage->class_implements[$generic_class_lc])) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-implements must include the name of an implemented class,'
|
||||||
'@template-implements must include the name of an implemented class,'
|
. ' got ' . $atomic_type->getId(),
|
||||||
. ' got ' . $atomic_type->getId(),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1559,15 +1460,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
string $used_class_name
|
string $used_class_name
|
||||||
) {
|
) {
|
||||||
if (trim($used_class_name) === '') {
|
if (trim($used_class_name) === '') {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Extended class cannot be empty in docblock for ' . implode('.', $this->fq_classlike_names),
|
||||||
'Extended class cannot be empty in docblock for ' . implode('.', $this->fq_classlike_names),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1584,29 +1480,19 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$this->class_template_types
|
$this->class_template_types
|
||||||
);
|
);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
||||||
$e->getMessage() . ' in docblock for ' . implode('.', $this->fq_classlike_names),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$used_union_type->isSingle()) {
|
if (!$used_union_type->isSingle()) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-use cannot be a union type',
|
||||||
'@template-use cannot be a union type',
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1621,15 +1507,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
foreach ($used_union_type->getAtomicTypes() as $atomic_type) {
|
foreach ($used_union_type->getAtomicTypes() as $atomic_type) {
|
||||||
if (!$atomic_type instanceof Type\Atomic\TGenericObject) {
|
if (!$atomic_type instanceof Type\Atomic\TGenericObject) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-use has invalid class ' . $atomic_type->getId(),
|
||||||
'@template-use has invalid class ' . $atomic_type->getId(),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1637,16 +1518,11 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$generic_class_lc = strtolower($atomic_type->value);
|
$generic_class_lc = strtolower($atomic_type->value);
|
||||||
|
|
||||||
if (!isset($storage->used_traits[$generic_class_lc])) {
|
if (!isset($storage->used_traits[$generic_class_lc])) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'@template-use must include the name of an used class,'
|
||||||
'@template-use must include the name of an used class,'
|
. ' got ' . $atomic_type->getId(),
|
||||||
. ' got ' . $atomic_type->getId(),
|
new CodeLocation($this->file_scanner, $node, null, true)
|
||||||
new CodeLocation($this->file_scanner, $node, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1901,15 +1777,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
foreach ($stmt->getParams() as $param) {
|
foreach ($stmt->getParams() as $param) {
|
||||||
if ($param->var instanceof PhpParser\Node\Expr\Error) {
|
if ($param->var instanceof PhpParser\Node\Expr\Error) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Param' . ($i + 1) . ' of ' . $cased_function_id . ' has invalid syntax',
|
||||||
'Param' . ($i + 1) . ' of ' . $cased_function_id . ' has invalid syntax',
|
new CodeLocation($this->file_scanner, $param, null, true)
|
||||||
new CodeLocation($this->file_scanner, $param, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
++$i;
|
++$i;
|
||||||
|
|
||||||
@ -1919,15 +1790,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$param_array = $this->getTranslatedFunctionParam($param, $stmt, $fake_method, $fq_classlike_name);
|
$param_array = $this->getTranslatedFunctionParam($param, $stmt, $fake_method, $fq_classlike_name);
|
||||||
|
|
||||||
if (isset($existing_params['$' . $param_array->name])) {
|
if (isset($existing_params['$' . $param_array->name])) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new DuplicateParam(
|
||||||
new DuplicateParam(
|
'Duplicate param $' . $param_array->name . ' in docblock for ' . $cased_function_id,
|
||||||
'Duplicate param $' . $param_array->name . ' in docblock for ' . $cased_function_id,
|
new CodeLocation($this->file_scanner, $param, null, true)
|
||||||
new CodeLocation($this->file_scanner, $param, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
++$i;
|
++$i;
|
||||||
|
|
||||||
@ -2136,26 +2002,17 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
try {
|
try {
|
||||||
$docblock_info = CommentAnalyzer::extractFunctionDocblockInfo($doc_comment);
|
$docblock_info = CommentAnalyzer::extractFunctionDocblockInfo($doc_comment);
|
||||||
} catch (IncorrectDocblockException $e) {
|
} catch (IncorrectDocblockException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new MissingDocblockType(
|
||||||
new MissingDocblockType(
|
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
||||||
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
$docblock_info = null;
|
$docblock_info = null;
|
||||||
} catch (DocblockParseException $e) {
|
} catch (DocblockParseException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
||||||
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
$docblock_info = null;
|
$docblock_info = null;
|
||||||
}
|
}
|
||||||
@ -2270,28 +2127,18 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$storage->template_types + ($template_types ?: [])
|
$storage->template_types + ($template_types ?: [])
|
||||||
);
|
);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Template ' . $template_name . ' has invalid as type - ' . $e->getMessage(),
|
||||||
'Template ' . $template_name . ' has invalid as type - ' . $e->getMessage(),
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
$template_type = Type::getMixed();
|
$template_type = Type::getMixed();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Template ' . $template_name . ' missing as type',
|
||||||
'Template ' . $template_name . ' missing as type',
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
$template_type = Type::getMixed();
|
$template_type = Type::getMixed();
|
||||||
}
|
}
|
||||||
@ -2300,16 +2147,11 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isset($template_types[$template_name])) {
|
if (isset($template_types[$template_name])) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Duplicate template param ' . $template_name . ' in docblock for '
|
||||||
'Duplicate template param ' . $template_name . ' in docblock for '
|
. $cased_function_id,
|
||||||
. $cased_function_id,
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
} else {
|
} else {
|
||||||
$storage->template_types[$template_name] = [
|
$storage->template_types[$template_name] = [
|
||||||
'fn-' . strtolower($cased_function_id) => [$template_type],
|
'fn-' . strtolower($cased_function_id) => [$template_type],
|
||||||
@ -2328,7 +2170,11 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$storage->assertions = [];
|
$storage->assertions = [];
|
||||||
|
|
||||||
foreach ($docblock_info->assertions as $assertion) {
|
foreach ($docblock_info->assertions as $assertion) {
|
||||||
$assertion_type_parts = $this->getAssertionParts($assertion['type'], $stmt);
|
$assertion_type_parts = $this->getAssertionParts(
|
||||||
|
$storage,
|
||||||
|
$assertion['type'],
|
||||||
|
$stmt
|
||||||
|
);
|
||||||
|
|
||||||
if (!$assertion_type_parts) {
|
if (!$assertion_type_parts) {
|
||||||
continue;
|
continue;
|
||||||
@ -2355,7 +2201,11 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$storage->if_true_assertions = [];
|
$storage->if_true_assertions = [];
|
||||||
|
|
||||||
foreach ($docblock_info->if_true_assertions as $assertion) {
|
foreach ($docblock_info->if_true_assertions as $assertion) {
|
||||||
$assertion_type_parts = $this->getAssertionParts($assertion['type'], $stmt);
|
$assertion_type_parts = $this->getAssertionParts(
|
||||||
|
$storage,
|
||||||
|
$assertion['type'],
|
||||||
|
$stmt
|
||||||
|
);
|
||||||
|
|
||||||
if (!$assertion_type_parts) {
|
if (!$assertion_type_parts) {
|
||||||
continue;
|
continue;
|
||||||
@ -2382,7 +2232,11 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$storage->if_false_assertions = [];
|
$storage->if_false_assertions = [];
|
||||||
|
|
||||||
foreach ($docblock_info->if_false_assertions as $assertion) {
|
foreach ($docblock_info->if_false_assertions as $assertion) {
|
||||||
$assertion_type_parts = $this->getAssertionParts($assertion['type'], $stmt);
|
$assertion_type_parts = $this->getAssertionParts(
|
||||||
|
$storage,
|
||||||
|
$assertion['type'],
|
||||||
|
$stmt
|
||||||
|
);
|
||||||
|
|
||||||
if (!$assertion_type_parts) {
|
if (!$assertion_type_parts) {
|
||||||
continue;
|
continue;
|
||||||
@ -2417,15 +2271,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
||||||
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2468,15 +2317,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$this->function_template_types + $class_template_types
|
$this->function_template_types + $class_template_types
|
||||||
);
|
);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
||||||
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2630,15 +2474,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
$storage->return_type->queueClassLikesForScanning($this->codebase, $this->file_storage);
|
$storage->return_type->queueClassLikesForScanning($this->codebase, $this->file_storage);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
||||||
$e->getMessage() . ' in docblock for ' . $cased_function_id,
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($storage->return_type && $docblock_info->ignore_nullable_return) {
|
if ($storage->return_type && $docblock_info->ignore_nullable_return) {
|
||||||
@ -2742,6 +2581,7 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
* @return ?list<string>
|
* @return ?list<string>
|
||||||
*/
|
*/
|
||||||
private function getAssertionParts(
|
private function getAssertionParts(
|
||||||
|
FunctionLikeStorage $storage,
|
||||||
string $assertion_type,
|
string $assertion_type,
|
||||||
PhpParser\Node\FunctionLike $stmt
|
PhpParser\Node\FunctionLike $stmt
|
||||||
) : ?array {
|
) : ?array {
|
||||||
@ -2779,16 +2619,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
);
|
);
|
||||||
|
|
||||||
if ($prefix && count($namespaced_type->getAtomicTypes()) > 1) {
|
if ($prefix && count($namespaced_type->getAtomicTypes()) > 1) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
'Docblock assertions cannot contain | characters together with ' . $prefix,
|
||||||
'Docblock assertions cannot contain | characters together with ' . $prefix,
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->file_storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -3039,15 +2873,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$this->function_template_types + $class_template_types
|
$this->function_template_types + $class_template_types
|
||||||
);
|
);
|
||||||
} catch (TypeParseTreeException $e) {
|
} catch (TypeParseTreeException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage() . ' in docblock for ' . $cased_method_id,
|
||||||
$e->getMessage() . ' in docblock for ' . $cased_method_id,
|
$docblock_type_location
|
||||||
$docblock_type_location
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -3199,25 +3028,15 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
$var_comment = array_pop($var_comments);
|
$var_comment = array_pop($var_comments);
|
||||||
} catch (IncorrectDocblockException $e) {
|
} catch (IncorrectDocblockException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new MissingDocblockType(
|
||||||
new MissingDocblockType(
|
$e->getMessage(),
|
||||||
$e->getMessage(),
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
} catch (DocblockParseException $e) {
|
} catch (DocblockParseException $e) {
|
||||||
if (IssueBuffer::accepts(
|
$storage->docblock_issues[] = new InvalidDocblock(
|
||||||
new InvalidDocblock(
|
$e->getMessage(),
|
||||||
$e->getMessage(),
|
new CodeLocation($this->file_scanner, $stmt, null, true)
|
||||||
new CodeLocation($this->file_scanner, $stmt, null, true)
|
);
|
||||||
)
|
|
||||||
)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$storage->has_docblock_issues = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,6 @@ class FileScanner implements FileSource
|
|||||||
|
|
||||||
if ((!$this->will_analyze || $file_storage->deep_scan)
|
if ((!$this->will_analyze || $file_storage->deep_scan)
|
||||||
&& $storage_from_cache
|
&& $storage_from_cache
|
||||||
&& !$file_storage->has_docblock_issues
|
|
||||||
&& !$codebase->register_stub_files
|
&& !$codebase->register_stub_files
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
|
@ -384,9 +384,9 @@ class ClassLikeStorage
|
|||||||
public $has_visitor_issues = false;
|
public $has_visitor_issues = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var list<\Psalm\Issue\CodeIssue>
|
||||||
*/
|
*/
|
||||||
public $has_docblock_issues = false;
|
public $docblock_issues = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
@ -77,9 +77,9 @@ class FileStorage
|
|||||||
public $has_visitor_issues = false;
|
public $has_visitor_issues = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var list<\Psalm\Issue\CodeIssue>
|
||||||
*/
|
*/
|
||||||
public $has_docblock_issues = false;
|
public $docblock_issues = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<string, array<int, array{0: string, 1: int}>>
|
* @var array<string, array<int, array{0: string, 1: int}>>
|
||||||
|
@ -142,9 +142,9 @@ class FunctionLikeStorage
|
|||||||
public $has_visitor_issues = false;
|
public $has_visitor_issues = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var list<\Psalm\Issue\CodeIssue>
|
||||||
*/
|
*/
|
||||||
public $has_docblock_issues = false;
|
public $docblock_issues = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<string, bool>
|
* @var array<string, bool>
|
||||||
|
Loading…
Reference in New Issue
Block a user