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

PSR-2 adjustments and adding PHPCS checks into the Travis config. (#149)

* PSR-2 adjustments and adding PHPCS checks into the Travis config.

* Reverting some CallChecker changes and no longer casting vars to null.
This commit is contained in:
Jon Ursenbach 2017-04-28 00:31:55 -04:00 committed by Matthew Brown
parent f71b4601e0
commit f65c618b2e
19 changed files with 127 additions and 59 deletions

View File

@ -15,3 +15,4 @@ install:
script:
- vendor/bin/phpunit
- bin/psalm
- vendor/bin/phpcs

View File

@ -3,10 +3,14 @@
<rule ref="PSR2" />
<file>bin/</file>
<file>examples/</file>
<file>src/</file>
<file>tests/</file>
<!-- This is a vendor file that we don't want to bother linting. -->
<exclude-pattern>src/Psalm/CallMap.php</exclude-pattern>
<!-- These are just examples and stub classes/files, so it doesn't really matter if they're PSR-2 compliant. -->
<exclude-pattern>examples/</exclude-pattern>
<exclude-pattern>src/Psalm/Stubs/</exclude-pattern>
<exclude-pattern>tests/stubs/</exclude-pattern>
</ruleset>

View File

@ -11,8 +11,7 @@ use Psalm\Type;
class CommentChecker
{
const TYPE_REGEX =
'(\??\\\?[\(\)A-Za-z0-9_\<,\>\[\]\-\{\}:|\\\]+|\$[a-zA-Z_0-9_\<,\>\|\[\]-\{\}:]+)';
const TYPE_REGEX = '(\??\\\?[\(\)A-Za-z0-9_\<,\>\[\]\-\{\}:|\\\]+|\$[a-zA-Z_0-9_\<,\>\|\[\]-\{\}:]+)';
/**
* @param string $comment
@ -78,7 +77,6 @@ class CommentChecker
break;
}
}
}
if (!$type_in_comments) {

View File

@ -98,7 +98,9 @@ class FunctionChecker extends FunctionLikeChecker
$file_storage = FileChecker::$storage[$file_path];
if (!isset($file_storage->functions[$function_id])) {
throw new \UnexpectedValueException('Not expecting ' . $function_id . ' to not have storage in ' . $file_path);
throw new \UnexpectedValueException(
'Not expecting ' . $function_id . ' to not have storage in ' . $file_path
);
}
return $file_storage->functions[$function_id];
@ -204,7 +206,12 @@ class FunctionChecker extends FunctionLikeChecker
$function_type_options = [];
if (!self::$callmap_file_checker) {
self::$callmap_file_checker = new FileChecker('callmap.php', \Psalm\Checker\ProjectChecker::getInstance(), [], false);
self::$callmap_file_checker = new FileChecker(
'callmap.php',
\Psalm\Checker\ProjectChecker::getInstance(),
[],
false
);
}
foreach ($call_map_functions as $call_map_function_args) {
@ -441,8 +448,13 @@ class FunctionChecker extends FunctionLikeChecker
$second_arg = isset($call_args[1]->value) ? $call_args[1]->value : null;
$inner_type = $first_arg_array instanceof Type\Atomic\TArray ? $first_arg_array->type_params[1] : $first_arg_array->getGenericTypeParam();
$key_type = $first_arg_array instanceof Type\Atomic\TArray ? clone $first_arg_array->type_params[0] : Type::getString();
if ($first_arg_array instanceof Type\Atomic\TArray) {
$inner_type = $first_arg_array->type_params[1];
$key_type = clone $first_arg_array->type_params[0];
} else {
$inner_type = $first_arg_array->getGenericTypeParam();
$key_type = Type::getString();
}
if (!$second_arg) {
$inner_type->removeType('null');
@ -602,24 +614,28 @@ class FunctionChecker extends FunctionLikeChecker
return substr($function_name, 1);
}
$function_name_lcase = strtolower($function_name);
$imported_function_namespaces = $source->getAliasedFunctions();
$imported_namespaces = $source->getAliasedClasses();
if (strpos($function_name, '\\') !== false) {
$function_name_parts = explode('\\', $function_name);
$first_namespace = array_shift($function_name_parts);
$first_namespace_lcase = strtolower($first_namespace);
if (isset($imported_namespaces[strtolower($first_namespace)])) {
return $imported_namespaces[strtolower($first_namespace)] . '\\' . implode('\\', $function_name_parts);
if (isset($imported_namespaces[$first_namespace_lcase])) {
return $imported_namespaces[$first_namespace_lcase] . '\\' . implode('\\', $function_name_parts);
}
if (isset($imported_function_namespaces[strtolower($first_namespace)])) {
return $imported_function_namespaces[strtolower($first_namespace)] . '\\' . implode('\\', $function_name_parts);
if (isset($imported_function_namespaces[$first_namespace_lcase])) {
return $imported_function_namespaces[$first_namespace_lcase] . '\\' .
implode('\\', $function_name_parts);
}
} elseif (isset($imported_namespaces[strtolower($function_name)])) {
return $imported_namespaces[strtolower($function_name)];
} elseif (isset($imported_function_namespaces[strtolower($function_name)])) {
return $imported_function_namespaces[strtolower($function_name)];
} elseif (isset($imported_namespaces[$function_name_lcase])) {
return $imported_namespaces[$function_name_lcase];
} elseif (isset($imported_function_namespaces[$function_name_lcase])) {
return $imported_function_namespaces[$function_name_lcase];
}
$namespace = $source->getNamespace();

View File

@ -870,7 +870,8 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
}
if ($this->function instanceof Function_) {
return ($this->source->getNamespace() ? strtolower($this->source->getNamespace()) . '\\' : '') . strtolower($this->function->name);
return ($this->source->getNamespace() ? strtolower($this->source->getNamespace()) . '\\' : '') .
strtolower($this->function->name);
}
return null;
@ -881,7 +882,10 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
*/
public function getAliasedClassesFlipped()
{
if ($this->source instanceof NamespaceChecker || $this->source instanceof FileChecker || $this->source instanceof ClassLikeChecker) {
if ($this->source instanceof NamespaceChecker ||
$this->source instanceof FileChecker ||
$this->source instanceof ClassLikeChecker
) {
return $this->source->getAliasedClassesFlipped();
}

View File

@ -69,7 +69,8 @@ class MethodChecker extends FunctionLikeChecker
* @param string $method_id
* @return Type\Union|null
*/
public static function getMethodReturnType($method_id) {
public static function getMethodReturnType($method_id)
{
$method_id = self::getDeclaringMethodId($method_id);
if (!$method_id) {
@ -243,7 +244,8 @@ class MethodChecker extends FunctionLikeChecker
if ($self_call) {
if (IssueBuffer::accepts(
new NonStaticSelfCall(
'Method ' . MethodChecker::getCasedMethodId($method_id) . ' is not static, but is called using self::',
'Method ' . MethodChecker::getCasedMethodId($method_id) . ' is not static, but is called ' .
'using self::',
$code_location
),
$suppressed_issues
@ -253,7 +255,8 @@ class MethodChecker extends FunctionLikeChecker
} else {
if (IssueBuffer::accepts(
new InvalidStaticInvocation(
'Method ' . MethodChecker::getCasedMethodId($method_id) . ' is not static, but is called statically',
'Method ' . MethodChecker::getCasedMethodId($method_id) . ' is not static, but is called ' .
'statically',
$code_location
),
$suppressed_issues
@ -524,8 +527,9 @@ class MethodChecker extends FunctionLikeChecker
public static function setDeclaringMethodId($method_id, $declaring_method_id)
{
list($fq_class_name, $method_name) = explode('::', $method_id);
$fq_class_name_lc = strtolower($fq_class_name);
ClassLikeChecker::$storage[strtolower($fq_class_name)]->declaring_method_ids[$method_name] = $declaring_method_id;
ClassLikeChecker::$storage[$fq_class_name_lc]->declaring_method_ids[$method_name] = $declaring_method_id;
}
/**
@ -536,8 +540,9 @@ class MethodChecker extends FunctionLikeChecker
public static function setAppearingMethodId($method_id, $appearing_method_id)
{
list($fq_class_name, $method_name) = explode('::', $method_id);
$fq_class_name_lc = strtolower($fq_class_name);
ClassLikeChecker::$storage[strtolower($fq_class_name)]->appearing_method_ids[$method_name] = $appearing_method_id;
ClassLikeChecker::$storage[$fq_class_name_lc]->appearing_method_ids[$method_name] = $appearing_method_id;
}
/**
@ -594,8 +599,9 @@ class MethodChecker extends FunctionLikeChecker
public static function setOverriddenMethodId($method_id, $overridden_method_id)
{
list($fq_class_name, $method_name) = explode('::', $method_id);
$fq_class_name_lc = strtolower($fq_class_name);
ClassLikeChecker::$storage[strtolower($fq_class_name)]->overridden_method_ids[$method_name][] = $overridden_method_id;
ClassLikeChecker::$storage[$fq_class_name_lc]->overridden_method_ids[$method_name][] = $overridden_method_id;
}
/**

View File

@ -983,7 +983,10 @@ class ProjectChecker
if (!$config) {
if ($this->output_format === self::TYPE_CONSOLE) {
exit('Could not locate a config XML file in path ' . $path . '. Have you run \'psalm --init\' ?' . PHP_EOL);
exit(
'Could not locate a config XML file in path ' . $path . '. Have you run \'psalm --init\' ?' .
PHP_EOL
);
}
throw new Exception\ConfigException('Config not found for path ' . $path);

View File

@ -488,7 +488,8 @@ class IfChecker
foreach ($all_negated_vars as $var_id) {
if (isset($negated_elseif_types[$var_id])) {
if (isset($if_scope->negated_types[$var_id])) {
$if_scope->negated_types[$var_id] = $if_scope->negated_types[$var_id] . '&' . $negated_elseif_types[$var_id];
$if_scope->negated_types[$var_id] = $if_scope->negated_types[$var_id] . '&' .
$negated_elseif_types[$var_id];
} else {
$if_scope->negated_types[$var_id] = $negated_elseif_types[$var_id];
}

View File

@ -32,7 +32,9 @@ class SwitchChecker
return false;
}
if (isset($stmt->cond->inferredType) && array_values($stmt->cond->inferredType->types)[0] instanceof Type\Atomic\T) {
if (isset($stmt->cond->inferredType) &&
array_values($stmt->cond->inferredType->types)[0] instanceof Type\Atomic\T
) {
/** @var Type\Atomic\T */
$type_type = array_values($stmt->cond->inferredType->types)[0];
$type_candidate_var = $type_type->typeof;

View File

@ -237,12 +237,16 @@ class AssignmentChecker
$context->vars_possibly_in_scope[$list_var_id] = true;
if (!$statements_checker->hasVariable($list_var_id)) {
$statements_checker->registerVariable($list_var_id, new CodeLocation($statements_checker, $var));
$statements_checker->registerVariable(
$list_var_id,
new CodeLocation($statements_checker, $var)
);
}
if (isset($assign_value_type->types['array'])) {
if ($assign_value_type->types['array'] instanceof Type\Atomic\TArray) {
$context->vars_in_scope[$list_var_id] = clone $assign_value_type->types['array']->type_params[1];
$context->vars_in_scope[$list_var_id] =
clone $assign_value_type->types['array']->type_params[1];
continue;
} elseif ($assign_value_type->types['array'] instanceof Type\Atomic\ObjectLike) {
@ -687,7 +691,6 @@ class AssignmentChecker
: Type::combineUnionTypes(Type::getNull(), $assignment_value_type);
}
}
} else {
$class_property_type = ExpressionChecker::fleshOutTypes(
clone $class_property_type,
@ -1037,7 +1040,8 @@ class AssignmentChecker
} elseif ($return_type->hasScalarType()) {
if (IssueBuffer::accepts(
new InvalidArrayAssignment(
'Cannot assign value on variable ' . $var_id . ' of scalar type ' . $context->vars_in_scope[$var_id],
'Cannot assign value on variable ' . $var_id . ' of scalar type ' .
$context->vars_in_scope[$var_id],
new CodeLocation($statements_checker->getSource(), $stmt)
),
$statements_checker->getSuppressedIssues()
@ -1117,7 +1121,6 @@ class AssignmentChecker
$context->vars_in_scope[$var_id] = $assignment_value_type;
}
}
}
}
} elseif ($var_id) {

View File

@ -341,7 +341,10 @@ class CallChecker
try {
if ($function_storage && $function_storage->return_type) {
if ($generic_params) {
$return_type = FunctionChecker::replaceTemplateTypes($function_storage->return_type, $generic_params);
$return_type = FunctionChecker::replaceTemplateTypes(
$function_storage->return_type,
$generic_params
);
} else {
$return_type = clone $function_storage->return_type;
}
@ -899,7 +902,10 @@ class CallChecker
if ($return_type_candidate) {
if ($class_template_params) {
$return_type_candidate = FunctionChecker::replaceTemplateTypes($return_type_candidate, $class_template_params);
$return_type_candidate = FunctionChecker::replaceTemplateTypes(
$return_type_candidate,
$class_template_params
);
} else {
$return_type_candidate = clone $return_type_candidate;
}
@ -910,7 +916,10 @@ class CallChecker
$method_id
);
$return_type_location = MethodChecker::getMethodReturnTypeLocation($method_id, $secondary_return_type_location);
$return_type_location = MethodChecker::getMethodReturnTypeLocation(
$method_id,
$secondary_return_type_location
);
if ($secondary_return_type_location) {
$return_type_location = $secondary_return_type_location;
@ -1243,7 +1252,10 @@ class CallChecker
if ($return_type_candidate) {
if ($found_generic_params) {
$return_type_candidate = FunctionChecker::replaceTemplateTypes($return_type_candidate, $found_generic_params);
$return_type_candidate = FunctionChecker::replaceTemplateTypes(
$return_type_candidate,
$found_generic_params
);
} else {
$return_type_candidate = clone $return_type_candidate;
}
@ -1254,7 +1266,10 @@ class CallChecker
$method_id
);
$return_type_location = MethodChecker::getMethodReturnTypeLocation($method_id, $secondary_return_type_location);
$return_type_location = MethodChecker::getMethodReturnTypeLocation(
$method_id,
$secondary_return_type_location
);
if ($secondary_return_type_location) {
$return_type_location = $secondary_return_type_location;
@ -1309,7 +1324,7 @@ class CallChecker
protected static function checkMethodArgs(
$method_id,
array $args,
array &$generic_params = null,
&$generic_params,
Context $context,
CodeLocation $code_location,
StatementsChecker $statements_checker
@ -1419,7 +1434,10 @@ class CallChecker
$context->vars_in_scope[$var_id] = Type::getMixed();
$context->vars_possibly_in_scope[$var_id] = true;
if (!$statements_checker->hasVariable($var_id)) {
$statements_checker->registerVariable($var_id, new CodeLocation($statements_checker, $arg->value));
$statements_checker->registerVariable(
$var_id,
new CodeLocation($statements_checker, $arg->value)
);
}
}
}
@ -1478,8 +1496,8 @@ class CallChecker
* @param array<int, PhpParser\Node\Arg> $args
* @param string|null $method_id
* @param array<int,FunctionLikeParameter> $function_params
* @param FunctionLikeStorage $function_storage
* @param ClassLikeStorage $class_storage
* @param FunctionLikeStorage|null $function_storage
* @param ClassLikeStorage|null $class_storage
* @param array<string, Type\Union>|null $generic_params
* @param CodeLocation $code_location
* @param bool $check_variables
@ -1490,9 +1508,9 @@ class CallChecker
array $args,
$method_id,
array $function_params,
FunctionLikeStorage $function_storage = null,
ClassLikeStorage $class_storage = null,
array &$generic_params = null,
$function_storage,
$class_storage,
&$generic_params,
CodeLocation $code_location,
$check_variables
) {

View File

@ -237,7 +237,9 @@ class FetchChecker
continue;
}
if ($stmt_var_id !== '$this' && MethodChecker::methodExists($lhs_type_part->value . '::__get', $file_checker)) {
if ($stmt_var_id !== '$this' &&
MethodChecker::methodExists($lhs_type_part->value . '::__get', $file_checker)
) {
$stmt->inferredType = Type::getMixed();
continue;
}
@ -1218,8 +1220,8 @@ class FetchChecker
) {
if (IssueBuffer::accepts(
new InvalidArrayAssignment(
'Cannot assign value on variable' . ($var_id ? ' ' . $var_id : '') . ' of type ' . $type . ' that does not ' .
'implement ArrayAccess',
'Cannot assign value on variable' . ($var_id ? ' ' . $var_id : '') . ' of type ' . $type .
' that does not implement ArrayAccess',
$code_location
),
$statements_checker->getSuppressedIssues()

View File

@ -229,7 +229,8 @@ class ExpressionChecker
}
$use_context = new Context($context->self);
$use_context->collect_references = $statements_checker->getFileChecker()->project_checker->collect_references;
$use_context->collect_references =
$statements_checker->getFileChecker()->project_checker->collect_references;
if (!$statements_checker->isStatic()) {
if ($context->collect_mutations &&

View File

@ -307,7 +307,6 @@ class StatementsChecker extends SourceChecker implements StatementsSource
$this->getSource()
);
}
} elseif ($stmt instanceof PhpParser\Node\Stmt\Goto_) {
// do nothing
} elseif ($stmt instanceof PhpParser\Node\Stmt\Label) {
@ -750,7 +749,9 @@ class StatementsChecker extends SourceChecker implements StatementsSource
$config = Config::getInstance();
if (!$config->allow_includes) {
throw new FileIncludeException('File includes are not allowed per your Psalm config - check the allowFileIncludes flag.');
throw new FileIncludeException(
'File includes are not allowed per your Psalm config - check the allowFileIncludes flag.'
);
}
if (ExpressionChecker::analyze($this, $stmt->expr, $context) === false) {

View File

@ -34,8 +34,6 @@ use Psalm\Type\Atomic\TNumericString;
class TypeChecker
{
/**
* Takes two arrays and consolidates them, removing null values from existing types where applicable
*
@ -798,7 +796,8 @@ class TypeChecker
ClassChecker::classExtendsOrImplements(
$container_type_part->value,
$input_type_part->value
)) ||
)
) ||
(InterfaceChecker::interfaceExists($container_type_part->value, $file_checker) &&
InterfaceChecker::interfaceExtends(
$container_type_part->value,

View File

@ -250,7 +250,9 @@ class Config
$errors = libxml_get_errors();
foreach ($errors as $error) {
if ($error->level === LIBXML_ERR_FATAL || $error->level === LIBXML_ERR_ERROR) {
throw new ConfigException('Error parsing file ' . $error->file . ' on line ' . $error->line . ': ' . $error->message);
throw new ConfigException(
'Error parsing file ' . $error->file . ' on line ' . $error->line . ': ' . $error->message
);
}
}
libxml_clear_errors();
@ -357,7 +359,9 @@ class Config
$file_path = realpath($stub_file['name']);
if (!$file_path) {
throw new Exception\ConfigException('Cannot resolve stubfile path ' . getcwd() . '/' . $stub_file['name']);
throw new Exception\ConfigException(
'Cannot resolve stubfile path ' . getcwd() . '/' . $stub_file['name']
);
}
$config->stub_files[] = $file_path;

View File

@ -60,7 +60,10 @@ class EffectsAnalyser
}
if ($stmt->finally) {
$return_types = array_merge($return_types, self::getReturnTypes($stmt->finally->stmts, $yield_types));
$return_types = array_merge(
$return_types,
self::getReturnTypes($stmt->finally->stmts, $yield_types)
);
}
} elseif ($stmt instanceof PhpParser\Node\Stmt\For_) {
$return_types = array_merge($return_types, self::getReturnTypes($stmt->stmts, $yield_types));

View File

@ -232,6 +232,4 @@ class FileReferenceProvider
file_put_contents($cache_location, serialize(self::$file_references));
}
}
}

View File

@ -67,7 +67,11 @@ class ObjectLike extends \Psalm\Type\Atomic
* @return string
*/
function ($name, Union $type) use ($aliased_classes, $this_class, $use_phpdoc_format) {
return $name . ':' . $type->toNamespacedString($aliased_classes, $this_class, $use_phpdoc_format);
return $name . ':' . $type->toNamespacedString(
$aliased_classes,
$this_class,
$use_phpdoc_format
);
},
array_keys($this->properties),
$this->properties