From c9493c54cdffe87b5e19baeb2ce9aade7093059d Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 14:00:08 +0200 Subject: [PATCH 01/63] First pass --- composer.json | 1 + examples/TemplateChecker.php | 2 +- examples/TemplateScanner.php | 2 +- examples/plugins/ClassUnqualifier.php | 2 +- examples/plugins/FunctionCasingChecker.php | 4 +- examples/plugins/InternalChecker.php | 2 +- examples/plugins/StringChecker.php | 4 +- src/Psalm/Aliases.php | 50 +-- src/Psalm/CodeLocation.php | 73 +--- src/Psalm/Codebase.php | 41 +- src/Psalm/Config.php | 33 +- src/Psalm/Config/Creator.php | 6 +- src/Psalm/Config/FileFilter.php | 18 +- src/Psalm/Config/ProjectFileFilter.php | 6 +- src/Psalm/Context.php | 21 +- src/Psalm/DocComment.php | 4 +- .../UnresolvableConstantException.php | 8 +- src/Psalm/FileBasedPluginAdapter.php | 10 +- src/Psalm/FileManipulation.php | 24 +- .../Internal/Analyzer/AlgebraAnalyzer.php | 2 +- src/Psalm/Internal/Analyzer/ClassAnalyzer.php | 10 +- .../Internal/Analyzer/ClassLikeAnalyzer.php | 10 +- .../Analyzer/ClassLikeNameOptions.php | 28 +- .../Internal/Analyzer/ClosureAnalyzer.php | 6 +- .../Internal/Analyzer/CommentAnalyzer.php | 5 +- .../Internal/Analyzer/DataFlowNodeData.php | 48 +-- src/Psalm/Internal/Analyzer/FileAnalyzer.php | 19 +- .../FunctionLike/ReturnTypeAnalyzer.php | 4 +- .../Analyzer/FunctionLikeAnalyzer.php | 30 +- .../Internal/Analyzer/InterfaceAnalyzer.php | 2 +- src/Psalm/Internal/Analyzer/IssueData.php | 169 +++----- .../Internal/Analyzer/MethodComparator.php | 8 +- .../Internal/Analyzer/NamespaceAnalyzer.php | 20 +- .../Internal/Analyzer/ProjectAnalyzer.php | 39 +- .../Analyzer/Statements/Block/DoAnalyzer.php | 6 +- .../Analyzer/Statements/Block/ForAnalyzer.php | 5 +- .../Statements/Block/ForeachAnalyzer.php | 16 +- .../Block/IfConditionalAnalyzer.php | 2 +- .../Statements/Block/IfElse/ElseAnalyzer.php | 17 +- .../Block/IfElse/ElseIfAnalyzer.php | 21 +- .../Statements/Block/IfElse/IfAnalyzer.php | 12 +- .../Statements/Block/IfElseAnalyzer.php | 16 +- .../Statements/Block/LoopAnalyzer.php | 22 +- .../Statements/Block/SwitchAnalyzer.php | 5 +- .../Statements/Block/SwitchCaseAnalyzer.php | 19 +- .../Analyzer/Statements/Block/TryAnalyzer.php | 2 +- .../Statements/Block/WhileAnalyzer.php | 6 +- .../Statements/Expression/AssertionFinder.php | 74 ++-- .../Assignment/ArrayAssignmentAnalyzer.php | 4 +- .../Assignment/AssignedProperty.php | 16 +- .../InstancePropertyAssignmentAnalyzer.php | 2 +- .../Expression/AssignmentAnalyzer.php | 14 +- .../Expression/BinaryOp/AndAnalyzer.php | 20 +- .../BinaryOp/ArithmeticOpAnalyzer.php | 6 +- .../Expression/BinaryOp/ConcatAnalyzer.php | 2 +- .../Expression/BinaryOp/OrAnalyzer.php | 35 +- .../Expression/BinaryOpAnalyzer.php | 4 +- .../Expression/Call/ArgumentAnalyzer.php | 6 +- .../Expression/Call/ArgumentsAnalyzer.php | 6 +- .../Call/ArrayFunctionArgumentsAnalyzer.php | 13 +- .../Expression/Call/FunctionCallAnalyzer.php | 7 +- .../Call/FunctionCallReturnTypeFetcher.php | 9 +- .../Call/HighOrderFunctionArgHandler.php | 6 +- .../Call/HighOrderFunctionArgInfo.php | 66 ++-- .../Call/Method/AtomicCallContext.php | 9 +- .../Call/Method/AtomicMethodCallAnalyzer.php | 3 +- .../ExistingAtomicMethodCallAnalyzer.php | 8 +- .../Call/NamedFunctionCallHandler.php | 3 +- .../Expression/Call/NewAnalyzer.php | 2 +- .../StaticMethod/AtomicStaticCallAnalyzer.php | 2 +- .../ExistingAtomicStaticCallAnalyzer.php | 5 +- .../Statements/Expression/CallAnalyzer.php | 15 +- .../Statements/Expression/CastAnalyzer.php | 16 +- .../Expression/ClassConstAnalyzer.php | 8 +- .../Fetch/AtomicPropertyFetchAnalyzer.php | 2 +- .../Fetch/VariableFetchAnalyzer.php | 8 +- .../Statements/Expression/IncludeAnalyzer.php | 2 +- .../Expression/SimpleTypeInferer.php | 8 +- .../Statements/Expression/TernaryAnalyzer.php | 23 +- .../Statements/ExpressionAnalyzer.php | 3 +- .../Analyzer/Statements/StaticAnalyzer.php | 2 +- .../Internal/Analyzer/StatementsAnalyzer.php | 21 +- src/Psalm/Internal/Analyzer/TraitAnalyzer.php | 5 +- src/Psalm/Internal/Cache.php | 5 +- src/Psalm/Internal/Clause.php | 19 +- src/Psalm/Internal/Cli/LanguageServer.php | 7 +- src/Psalm/Internal/Cli/Psalm.php | 16 +- src/Psalm/Internal/Cli/Psalter.php | 9 +- src/Psalm/Internal/Cli/Refactor.php | 3 +- src/Psalm/Internal/CliUtils.php | 3 +- src/Psalm/Internal/Codebase/Analyzer.php | 36 +- .../AssertionsFromInheritanceResolver.php | 14 +- .../ClassConstantByWildcardResolver.php | 6 +- src/Psalm/Internal/Codebase/ClassLikes.php | 44 +-- src/Psalm/Internal/Codebase/DataFlowGraph.php | 8 +- src/Psalm/Internal/Codebase/Functions.php | 28 +- .../Codebase/InternalCallMapHandler.php | 7 +- src/Psalm/Internal/Codebase/Methods.php | 21 +- src/Psalm/Internal/Codebase/Populator.php | 136 ++----- src/Psalm/Internal/Codebase/Properties.php | 15 +- src/Psalm/Internal/Codebase/Reflection.php | 15 +- src/Psalm/Internal/Codebase/Scanner.php | 41 +- .../Codebase/StorageByPatternResolver.php | 6 +- .../Internal/Codebase/TaintFlowGraph.php | 289 ++++++-------- .../Internal/Codebase/VariableUseGraph.php | 6 +- src/Psalm/Internal/DataFlow/DataFlowNode.php | 26 +- src/Psalm/Internal/DataFlow/Path.php | 22 +- .../Internal/Diff/ClassStatementsDiffer.php | 9 +- src/Psalm/Internal/Diff/DiffElem.php | 20 +- src/Psalm/Internal/Diff/FileDiffer.php | 2 +- .../Internal/Diff/FileStatementsDiffer.php | 3 +- .../Diff/NamespaceStatementsDiffer.php | 3 +- src/Psalm/Internal/ErrorHandler.php | 4 +- .../BuildInfoCollector.php | 24 +- .../ExecutionEnvironment/GitInfoCollector.php | 9 +- .../ClassDocblockManipulator.php | 11 +- .../FileManipulation/CodeMigration.php | 24 +- .../FunctionDocblockManipulator.php | 17 +- .../PropertyDocblockManipulator.php | 11 +- .../Internal/Fork/ForkProcessDoneMessage.php | 4 +- .../Internal/Fork/ForkProcessErrorMessage.php | 5 +- .../Internal/Fork/ForkTaskDoneMessage.php | 5 +- src/Psalm/Internal/Fork/Pool.php | 18 +- .../Client/Progress/LegacyProgress.php | 5 +- .../Client/Progress/Progress.php | 7 +- .../LanguageServer/Client/TextDocument.php | 8 +- .../LanguageServer/Client/Workspace.php | 22 +- .../LanguageServer/ClientConfiguration.php | 144 +++---- .../Internal/LanguageServer/ClientHandler.php | 8 +- .../LanguageServer/LanguageClient.php | 30 +- .../LanguageServer/LanguageServer.php | 59 +-- src/Psalm/Internal/LanguageServer/Message.php | 8 +- .../LanguageServer/PHPMarkdownContent.php | 12 +- .../Internal/LanguageServer/PathMapper.php | 7 +- .../LanguageServer/ProtocolStreamReader.php | 6 +- .../LanguageServer/ProtocolStreamWriter.php | 2 +- .../Provider/ParserCacheProvider.php | 12 +- .../Internal/LanguageServer/Reference.php | 9 +- .../LanguageServer/Server/TextDocument.php | 26 +- .../LanguageServer/Server/Workspace.php | 18 +- src/Psalm/Internal/MethodIdentifier.php | 15 +- .../PhpVisitor/AssignmentMapVisitor.php | 5 +- .../PhpVisitor/ConditionCloningVisitor.php | 5 +- .../PhpVisitor/NodeCleanerVisitor.php | 5 +- .../PhpVisitor/OffsetShifterVisitor.php | 12 +- .../PhpVisitor/ParamReplacementVisitor.php | 8 +- .../PhpVisitor/PartialParserVisitor.php | 30 +- .../Reflector/ClassLikeDocblockParser.php | 5 +- .../Reflector/ClassLikeNodeScanner.php | 36 +- .../Reflector/ExpressionResolver.php | 2 +- .../Reflector/ExpressionScanner.php | 6 +- .../Reflector/FunctionLikeDocblockParser.php | 10 +- .../Reflector/FunctionLikeDocblockScanner.php | 26 +- .../Reflector/FunctionLikeNodeScanner.php | 58 +-- .../Internal/PhpVisitor/ReflectorVisitor.php | 27 +- .../PhpVisitor/SimpleNameResolver.php | 2 +- src/Psalm/Internal/PhpVisitor/TraitFinder.php | 7 +- .../PhpVisitor/TypeMappingVisitor.php | 11 +- .../PhpVisitor/YieldTypeCollector.php | 7 +- .../PluginManager/Command/DisableCommand.php | 7 +- .../PluginManager/Command/EnableCommand.php | 7 +- .../PluginManager/Command/ShowCommand.php | 5 +- .../Internal/PluginManager/ComposerLock.php | 6 +- .../Internal/PluginManager/ConfigFile.php | 6 +- .../Internal/PluginManager/PluginList.php | 12 +- .../PluginManager/PluginListFactory.php | 10 +- .../ClassLikeStorageCacheProvider.php | 7 +- .../Provider/ClassLikeStorageProvider.php | 10 +- .../Internal/Provider/FakeFileProvider.php | 4 +- src/Psalm/Internal/Provider/FileProvider.php | 2 +- .../Provider/FileReferenceCacheProvider.php | 5 +- .../Provider/FileReferenceProvider.php | 11 +- .../Provider/FileStorageCacheProvider.php | 7 +- .../Internal/Provider/FileStorageProvider.php | 10 +- .../Internal/Provider/ParserCacheProvider.php | 9 +- .../Provider/ProjectCacheProvider.php | 5 +- src/Psalm/Internal/Provider/Providers.php | 16 +- .../ArrayFillReturnTypeProvider.php | 2 +- .../ArrayFilterReturnTypeProvider.php | 2 +- .../ArrayMapReturnTypeProvider.php | 6 +- ...rayPointerAdjustmentReturnTypeProvider.php | 2 +- .../ArrayReduceReturnTypeProvider.php | 4 +- .../MinMaxReturnTypeProvider.php | 3 +- .../PdoStatementReturnTypeProvider.php | 362 ++++++++---------- .../SprintfReturnTypeProvider.php | 2 +- .../Internal/Provider/StatementsProvider.php | 32 +- src/Psalm/Internal/Scanner/DocblockParser.php | 15 +- src/Psalm/Internal/Scanner/FileScanner.php | 11 +- src/Psalm/Internal/Scanner/ParsedDocblock.php | 12 +- .../Internal/Scanner/PhpStormMetaScanner.php | 10 +- .../UnresolvedConstant/ArrayOffsetFetch.php | 8 +- .../UnresolvedConstant/ArraySpread.php | 5 +- .../Scanner/UnresolvedConstant/ArrayValue.php | 6 +- .../UnresolvedConstant/ClassConstant.php | 8 +- .../Scanner/UnresolvedConstant/Constant.php | 8 +- .../UnresolvedConstant/EnumPropertyFetch.php | 8 +- .../UnresolvedConstant/KeyValuePair.php | 8 +- .../UnresolvedConstant/ScalarValue.php | 5 +- .../UnresolvedConstant/UnresolvedBinaryOp.php | 8 +- .../UnresolvedConstant/UnresolvedTernary.php | 16 +- src/Psalm/Internal/Scope/CaseScope.php | 5 +- src/Psalm/Internal/Scope/FinallyScope.php | 8 +- .../Internal/Scope/IfConditionalScope.php | 31 +- src/Psalm/Internal/Scope/LoopScope.php | 8 +- .../Generator/ClassLikeStubGenerator.php | 32 +- .../Stubs/Generator/StubsGenerator.php | 8 +- src/Psalm/Internal/Type/ArrayType.php | 14 +- .../Internal/Type/AssertionReconciler.php | 7 +- .../Type/Comparator/AtomicTypeComparator.php | 19 +- .../Comparator/CallableTypeComparator.php | 6 +- .../Comparator/ClassLikeStringComparator.php | 4 +- .../Comparator/IntegerRangeComparator.php | 5 +- .../Type/Comparator/ObjectComparator.php | 21 +- .../Type/Comparator/ScalarTypeComparator.php | 49 ++- .../Type/NegatedAssertionReconciler.php | 9 +- src/Psalm/Internal/Type/ParseTree.php | 5 +- .../Internal/Type/ParseTree/CallableTree.php | 5 +- .../Type/ParseTree/ConditionalTree.php | 5 +- .../Internal/Type/ParseTree/GenericTree.php | 5 +- .../Type/ParseTree/IndexedAccessTree.php | 5 +- .../Type/ParseTree/KeyedArrayPropertyTree.php | 5 +- .../Type/ParseTree/KeyedArrayTree.php | 5 +- .../Type/ParseTree/MethodParamTree.php | 15 +- .../Internal/Type/ParseTree/MethodTree.php | 5 +- .../Type/ParseTree/TemplateAsTree.php | 8 +- .../Type/ParseTree/TemplateIsTree.php | 5 +- src/Psalm/Internal/Type/ParseTree/Value.php | 15 +- src/Psalm/Internal/Type/ParseTreeCreator.php | 8 +- .../Type/SimpleAssertionReconciler.php | 35 +- .../Type/SimpleNegatedAssertionReconciler.php | 25 +- src/Psalm/Internal/Type/TemplateBound.php | 50 +-- .../Type/TemplateInferredTypeReplacer.php | 8 +- src/Psalm/Internal/Type/TemplateResult.php | 15 +- .../Type/TemplateStandinTypeReplacer.php | 7 +- .../Type/TypeAlias/ClassTypeAlias.php | 8 +- .../Type/TypeAlias/InlineTypeAlias.php | 8 +- .../Type/TypeAlias/LinkableTypeAlias.php | 24 +- src/Psalm/Internal/Type/TypeCombiner.php | 63 ++- src/Psalm/Internal/Type/TypeExpander.php | 12 +- src/Psalm/Internal/Type/TypeParser.php | 23 +- src/Psalm/Internal/Type/TypeTokenizer.php | 40 +- .../CanContainObjectTypeVisitor.php | 5 +- .../TypeVisitor/ClasslikeReplacer.php | 6 +- .../TypeVisitor/ContainsClassLikeVisitor.php | 8 +- .../TypeVisitor/FromDocblockSetter.php | 4 +- .../Internal/TypeVisitor/TypeChecker.php | 51 +-- .../Internal/TypeVisitor/TypeLocalizer.php | 14 +- .../Internal/TypeVisitor/TypeScanner.php | 19 +- src/Psalm/Internal/VersionUtils.php | 2 +- src/Psalm/Issue/ClassConstantIssue.php | 5 +- src/Psalm/Issue/ClassIssue.php | 5 +- src/Psalm/Issue/CodeIssue.php | 22 +- .../Issue/InvalidInterfaceImplementation.php | 4 +- src/Psalm/Issue/PrivateFinalMethod.php | 4 +- src/Psalm/Issue/PropertyIssue.php | 5 +- src/Psalm/Issue/RiskyCast.php | 4 +- src/Psalm/Issue/TaintedInput.php | 24 +- src/Psalm/Issue/UnusedBaselineEntry.php | 4 +- src/Psalm/IssueBuffer.php | 117 ++---- src/Psalm/Plugin/ArgTypeInferer.php | 7 +- src/Psalm/Plugin/DynamicTemplateProvider.php | 5 +- .../Event/AddRemoveTaintsEvent.php | 17 +- .../EventHandler/Event/AfterAnalysisEvent.php | 20 +- .../Event/AfterClassLikeAnalysisEvent.php | 23 +- .../AfterClassLikeExistenceCheckEvent.php | 23 +- .../Event/AfterClassLikeVisitEvent.php | 23 +- .../Event/AfterCodebasePopulatedEvent.php | 5 +- .../AfterEveryFunctionCallAnalysisEvent.php | 20 +- .../Event/AfterExpressionAnalysisEvent.php | 23 +- .../Event/AfterFileAnalysisEvent.php | 23 +- .../Event/AfterFunctionCallAnalysisEvent.php | 32 +- .../Event/AfterFunctionLikeAnalysisEvent.php | 29 +- .../Event/AfterMethodCallAnalysisEvent.php | 36 +- .../Event/AfterStatementAnalysisEvent.php | 23 +- .../Event/BeforeAddIssueEvent.php | 9 +- .../Event/BeforeExpressionAnalysisEvent.php | 23 +- .../Event/BeforeFileAnalysisEvent.php | 17 +- .../Event/BeforeStatementAnalysisEvent.php | 23 +- .../DynamicFunctionStorageProviderEvent.php | 26 +- .../Event/FunctionExistenceProviderEvent.php | 11 +- .../Event/FunctionParamsProviderEvent.php | 23 +- .../Event/FunctionReturnTypeProviderEvent.php | 23 +- .../Event/MethodExistenceProviderEvent.php | 17 +- .../Event/MethodParamsProviderEvent.php | 26 +- .../Event/MethodReturnTypeProviderEvent.php | 39 +- .../Event/MethodVisibilityProviderEvent.php | 20 +- .../Event/PropertyExistenceProviderEvent.php | 23 +- .../Event/PropertyTypeProviderEvent.php | 20 +- .../Event/PropertyVisibilityProviderEvent.php | 23 +- .../Event/StringInterpreterEvent.php | 7 +- src/Psalm/PluginFileExtensionsSocket.php | 5 +- src/Psalm/PluginRegistrationSocket.php | 8 +- src/Psalm/Progress/LongProgress.php | 10 +- src/Psalm/Report.php | 51 +-- .../Report/ByIssueLevelAndTypeReport.php | 3 +- src/Psalm/Report/CodeClimateReport.php | 2 +- src/Psalm/Report/ConsoleReport.php | 3 +- src/Psalm/Report/SarifReport.php | 4 +- src/Psalm/SourceControl/Git/GitInfo.php | 30 +- src/Psalm/Storage/Assertion.php | 3 +- .../Assertion/DoesNotHaveAtLeastCount.php | 6 +- .../Assertion/DoesNotHaveExactCount.php | 6 +- .../Storage/Assertion/DoesNotHaveMethod.php | 5 +- .../Storage/Assertion/HasAtLeastCount.php | 6 +- src/Psalm/Storage/Assertion/HasExactCount.php | 6 +- src/Psalm/Storage/Assertion/HasMethod.php | 5 +- src/Psalm/Storage/Assertion/InArray.php | 5 +- src/Psalm/Storage/Assertion/IsAClass.php | 8 +- src/Psalm/Storage/Assertion/IsClassEqual.php | 5 +- .../Storage/Assertion/IsClassNotEqual.php | 5 +- src/Psalm/Storage/Assertion/IsGreaterThan.php | 5 +- .../Assertion/IsGreaterThanOrEqualTo.php | 5 +- src/Psalm/Storage/Assertion/IsIdentical.php | 5 +- src/Psalm/Storage/Assertion/IsLessThan.php | 5 +- .../Storage/Assertion/IsLessThanOrEqualTo.php | 5 +- .../Storage/Assertion/IsLooselyEqual.php | 5 +- src/Psalm/Storage/Assertion/IsNotAClass.php | 8 +- .../Storage/Assertion/IsNotIdentical.php | 5 +- .../Storage/Assertion/IsNotLooselyEqual.php | 5 +- src/Psalm/Storage/Assertion/IsNotType.php | 5 +- src/Psalm/Storage/Assertion/IsType.php | 5 +- .../Storage/Assertion/NestedAssertions.php | 6 +- src/Psalm/Storage/Assertion/NotInArray.php | 14 +- .../Storage/Assertion/NotNestedAssertions.php | 6 +- src/Psalm/Storage/AttributeArg.php | 26 +- src/Psalm/Storage/AttributeStorage.php | 34 +- src/Psalm/Storage/ClassConstantStorage.php | 98 ++--- src/Psalm/Storage/ClassLikeStorage.php | 5 +- src/Psalm/Storage/EnumCaseStorage.php | 12 +- src/Psalm/Storage/FileStorage.php | 5 +- src/Psalm/Storage/FunctionLikeParameter.php | 55 +-- src/Psalm/Storage/FunctionLikeStorage.php | 37 +- src/Psalm/Storage/Possibilities.php | 23 +- src/Psalm/Storage/PropertyStorage.php | 17 +- src/Psalm/Type.php | 22 +- src/Psalm/Type/Atomic.php | 23 +- src/Psalm/Type/Atomic/GenericTrait.php | 4 +- .../Type/Atomic/TAnonymousClassInstance.php | 6 +- src/Psalm/Type/Atomic/TArray.php | 3 +- src/Psalm/Type/Atomic/TCallableObject.php | 5 +- src/Psalm/Type/Atomic/TClassConstant.php | 8 +- src/Psalm/Type/Atomic/TClassString.php | 29 +- src/Psalm/Type/Atomic/TClassStringMap.php | 19 +- src/Psalm/Type/Atomic/TClosure.php | 10 +- src/Psalm/Type/Atomic/TConditional.php | 30 +- src/Psalm/Type/Atomic/TDependentGetClass.php | 11 +- .../Type/Atomic/TDependentGetDebugType.php | 8 +- src/Psalm/Type/Atomic/TDependentGetType.php | 8 +- src/Psalm/Type/Atomic/TEnumCase.php | 6 +- src/Psalm/Type/Atomic/TGenericObject.php | 10 +- src/Psalm/Type/Atomic/TIntMask.php | 6 +- src/Psalm/Type/Atomic/TIntMaskOf.php | 10 +- src/Psalm/Type/Atomic/TIntRange.php | 14 +- src/Psalm/Type/Atomic/TKeyOf.php | 5 +- src/Psalm/Type/Atomic/TKeyedArray.php | 19 +- src/Psalm/Type/Atomic/TLiteralClassString.php | 19 +- src/Psalm/Type/Atomic/TLiteralFloat.php | 5 +- src/Psalm/Type/Atomic/TLiteralInt.php | 5 +- src/Psalm/Type/Atomic/TMixed.php | 5 +- src/Psalm/Type/Atomic/TNamedObject.php | 16 +- src/Psalm/Type/Atomic/TNonEmptyArray.php | 21 +- .../Type/Atomic/TObjectWithProperties.php | 16 +- src/Psalm/Type/Atomic/TPropertiesOf.php | 44 +-- .../Type/Atomic/TTemplateIndexedAccess.php | 15 +- src/Psalm/Type/Atomic/TTemplateKeyOf.php | 15 +- src/Psalm/Type/Atomic/TTemplateParam.php | 15 +- src/Psalm/Type/Atomic/TTemplateParamClass.php | 10 +- .../Type/Atomic/TTemplatePropertiesOf.php | 20 +- src/Psalm/Type/Atomic/TTemplateValueOf.php | 15 +- src/Psalm/Type/Atomic/TTypeAlias.php | 27 +- src/Psalm/Type/Atomic/TUnknownClassString.php | 5 +- src/Psalm/Type/Atomic/TValueOf.php | 5 +- src/Psalm/Type/MutableUnion.php | 3 +- src/Psalm/Type/Reconciler.php | 16 +- src/Psalm/Type/Union.php | 2 +- src/Psalm/Type/UnionTrait.php | 15 +- tests/AsyncTestCase.php | 4 +- tests/BinaryOperationTest.php | 39 +- tests/CodebaseTest.php | 5 +- tests/Config/ConfigTest.php | 5 +- .../Plugin/FileTypeSelfRegisteringPlugin.php | 8 +- tests/Config/PluginTest.php | 7 +- tests/ConstantTest.php | 63 +-- tests/DocumentationTest.php | 23 +- tests/ExpressionTest.php | 43 ++- tests/FileDiffTest.php | 15 +- .../ClassConstantMoveTest.php | 4 +- tests/FileManipulation/ClassMoveTest.php | 4 +- .../FileManipulationTestCase.php | 3 +- tests/FileManipulation/MethodMoveTest.php | 4 +- tests/FileManipulation/NamespaceMoveTest.php | 4 +- tests/FileManipulation/PropertyMoveTest.php | 4 +- tests/FileReferenceTest.php | 6 +- tests/FileUpdates/AnalyzedMethodTest.php | 4 +- tests/FileUpdates/CachedStorageTest.php | 4 +- tests/IncludeTest.php | 4 +- .../Codebase/InternalCallMapHandlerTest.php | 27 +- .../Provider/ParserInstanceCacheProvider.php | 12 +- tests/LanguageServer/DiagnosticTest.php | 5 +- tests/LanguageServer/Message.php | 2 - tests/ProjectCheckerTest.php | 3 +- tests/TaintTest.php | 8 +- tests/TestCase.php | 4 +- tests/Traits/InvalidCodeAnalysisTestTrait.php | 8 +- tests/Traits/ValidCodeAnalysisTestTrait.php | 9 +- tests/TypeReconciliation/ReconcilerTest.php | 2 +- tests/UnusedCodeTest.php | 6 +- tests/fixtures/DummyProject/Bar.php | 3 +- tests/fixtures/ModularConfig/Bar.php | 3 +- 409 files changed, 1977 insertions(+), 4655 deletions(-) diff --git a/composer.json b/composer.json index 0a56c517c06..12fa649812c 100644 --- a/composer.json +++ b/composer.json @@ -57,6 +57,7 @@ "phpunit/phpunit": "^9.6", "psalm/plugin-mockery": "^1.1", "psalm/plugin-phpunit": "^0.18", + "rector/rector": "^0.18.5", "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.6", "symfony/process": "^4.4 || ^5.0 || ^6.0" diff --git a/examples/TemplateChecker.php b/examples/TemplateChecker.php index 60d0f822534..7fec45544dc 100644 --- a/examples/TemplateChecker.php +++ b/examples/TemplateChecker.php @@ -32,7 +32,7 @@ class TemplateAnalyzer extends Psalm\Internal\Analyzer\FileAnalyzer { - const VIEW_CLASS = 'Your\\View\\Class'; + final public const VIEW_CLASS = 'Your\\View\\Class'; public function analyze(?Context $file_context = null, ?Context $global_context = null): void { diff --git a/examples/TemplateScanner.php b/examples/TemplateScanner.php index d177f80e6b8..681bf61bdc7 100644 --- a/examples/TemplateScanner.php +++ b/examples/TemplateScanner.php @@ -16,7 +16,7 @@ class TemplateScanner extends Psalm\Internal\Scanner\FileScanner { - const VIEW_CLASS = 'Your\\View\\Class'; + final public const VIEW_CLASS = 'Your\\View\\Class'; public function scan( Codebase $codebase, diff --git a/examples/plugins/ClassUnqualifier.php b/examples/plugins/ClassUnqualifier.php index 3f4f14f517a..97cecee648c 100644 --- a/examples/plugins/ClassUnqualifier.php +++ b/examples/plugins/ClassUnqualifier.php @@ -29,7 +29,7 @@ public static function afterClassLikeExistenceCheck( return; } - if (strpos($candidate_type, '\\' . $fq_class_name) !== false) { + if (str_contains($candidate_type, '\\' . $fq_class_name)) { $type_tokens = TypeTokenizer::tokenize($candidate_type, false); foreach ($type_tokens as &$type_token) { diff --git a/examples/plugins/FunctionCasingChecker.php b/examples/plugins/FunctionCasingChecker.php index 50cfc7358ff..f4d8c6a2e3e 100644 --- a/examples/plugins/FunctionCasingChecker.php +++ b/examples/plugins/FunctionCasingChecker.php @@ -55,7 +55,7 @@ public static function afterMethodCallAnalysis(AfterMethodCallAnalysisEvent $eve $statements_source->getSuppressedIssues(), ); } - } catch (Exception $e) { + } catch (Exception) { // can throw if storage is missing } } @@ -93,7 +93,7 @@ public static function afterFunctionCallAnalysis(AfterFunctionCallAnalysisEvent $statements_source->getSuppressedIssues(), ); } - } catch (Exception $e) { + } catch (Exception) { // can throw if storage is missing } } diff --git a/examples/plugins/InternalChecker.php b/examples/plugins/InternalChecker.php index 1ae5d8afee9..a5c6306bab0 100644 --- a/examples/plugins/InternalChecker.php +++ b/examples/plugins/InternalChecker.php @@ -19,7 +19,7 @@ public static function afterStatementAnalysis(AfterClassLikeAnalysisEvent $event { $storage = $event->getClasslikeStorage(); if (!$storage->internal - && strpos($storage->name, 'Psalm\\Internal') === 0 + && str_starts_with($storage->name, 'Psalm\\Internal') && $storage->location ) { IssueBuffer::maybeAdd( diff --git a/examples/plugins/StringChecker.php b/examples/plugins/StringChecker.php index 43629bdf65e..070bcde5ac4 100644 --- a/examples/plugins/StringChecker.php +++ b/examples/plugins/StringChecker.php @@ -31,8 +31,8 @@ public static function afterExpressionAnalysis(AfterExpressionAnalysisEvent $eve if ($expr instanceof PhpParser\Node\Scalar\String_) { $class_or_class_method = '/^\\\?Psalm(\\\[A-Z][A-Za-z0-9]+)+(::[A-Za-z0-9]+)?$/'; - if (strpos($statements_source->getFileName(), 'base/DefinitionManager.php') === false - && strpos($expr->value, 'TestController') === false + if (!str_contains($statements_source->getFileName(), 'base/DefinitionManager.php') + && !str_contains($expr->value, 'TestController') && preg_match($class_or_class_method, $expr->value) ) { /** @psalm-suppress PossiblyInvalidArrayAccess */ diff --git a/src/Psalm/Aliases.php b/src/Psalm/Aliases.php index daa39b90a30..2dedcf01c1f 100644 --- a/src/Psalm/Aliases.php +++ b/src/Psalm/Aliases.php @@ -6,38 +6,6 @@ final class Aliases { - /** - * @var array - */ - public array $uses; - - /** - * @var array - */ - public array $uses_flipped; - - /** - * @var array - */ - public array $functions; - - /** - * @var array - */ - public array $functions_flipped; - - /** - * @var array - */ - public array $constants; - - /** - * @var array - */ - public array $constants_flipped; - - public ?string $namespace = null; - public ?int $namespace_first_stmt_start = null; public ?int $uses_start = null; @@ -54,21 +22,7 @@ final class Aliases * @internal * @psalm-mutation-free */ - public function __construct( - ?string $namespace = null, - array $uses = [], - array $functions = [], - array $constants = [], - array $uses_flipped = [], - array $functions_flipped = [], - array $constants_flipped = [], - ) { - $this->namespace = $namespace; - $this->uses = $uses; - $this->functions = $functions; - $this->constants = $constants; - $this->uses_flipped = $uses_flipped; - $this->functions_flipped = $functions_flipped; - $this->constants_flipped = $constants_flipped; + public function __construct(public ?string $namespace = null, public array $uses = [], public array $functions = [], public array $constants = [], public array $uses_flipped = [], public array $functions_flipped = [], public array $constants_flipped = []) + { } } diff --git a/src/Psalm/CodeLocation.php b/src/Psalm/CodeLocation.php index 9c35acfb340..b40b2aa528f 100644 --- a/src/Psalm/CodeLocation.php +++ b/src/Psalm/CodeLocation.php @@ -51,8 +51,6 @@ class CodeLocation protected int $file_end; - protected bool $single_line; - protected int $preview_start; private int $preview_end = -1; @@ -67,20 +65,12 @@ class CodeLocation private string $snippet = ''; - private ?string $text = null; - public ?int $docblock_start = null; private ?int $docblock_start_line_number = null; - protected ?int $docblock_line_number = null; - - private ?int $regex_type = null; - private bool $have_recalculated = false; - public ?CodeLocation $previous_location = null; - public const VAR_TYPE = 0; public const FUNCTION_RETURN_TYPE = 1; public const FUNCTION_PARAM_TYPE = 2; @@ -93,11 +83,11 @@ class CodeLocation public function __construct( FileSource $file_source, PhpParser\Node $stmt, - ?CodeLocation $previous_location = null, - bool $single_line = false, - ?int $regex_type = null, - ?string $selected_text = null, - ?int $comment_line = null, + public ?CodeLocation $previous_location = null, + protected bool $single_line = false, + private ?int $regex_type = null, + private ?string $text = null, + protected ?int $docblock_line_number = null, ) { /** @psalm-suppress ImpureMethodCall Actually mutation-free just not marked */ $this->file_start = (int)$stmt->getAttribute('startFilePos'); @@ -107,10 +97,6 @@ public function __construct( $this->raw_file_end = $this->file_end; $this->file_path = $file_source->getFilePath(); $this->file_name = $file_source->getFileName(); - $this->single_line = $single_line; - $this->regex_type = $regex_type; - $this->previous_location = $previous_location; - $this->text = $selected_text; /** @psalm-suppress ImpureMethodCall Actually mutation-free just not marked */ $doc_comment = $stmt->getDocComment(); @@ -122,8 +108,6 @@ public function __construct( /** @psalm-suppress ImpureMethodCall Actually mutation-free just not marked */ $this->raw_line_number = $stmt->getLine(); - - $this->docblock_line_number = $comment_line; } /** @@ -219,42 +203,17 @@ private function calculateRealLocation(): void } if ($this->regex_type !== null) { - switch ($this->regex_type) { - case self::VAR_TYPE: - $regex = '/@(?:psalm-)?var[ \t]+' . CommentAnalyzer::TYPE_REGEX . '/'; - break; - - case self::FUNCTION_RETURN_TYPE: - $regex = '/\\:\s+(\\??\s*[A-Za-z0-9_\\\\\[\]]+)/'; - break; - - case self::FUNCTION_PARAM_TYPE: - $regex = '/^(\\??\s*[A-Za-z0-9_\\\\\[\]]+)\s/'; - break; - - case self::FUNCTION_PHPDOC_RETURN_TYPE: - $regex = '/@(?:psalm-)?return[ \t]+' . CommentAnalyzer::TYPE_REGEX . '/'; - break; - - case self::FUNCTION_PHPDOC_METHOD: - $regex = '/@(?:psalm-)?method[ \t]+(.*)/'; - break; - - case self::FUNCTION_PHPDOC_PARAM_TYPE: - $regex = '/@(?:psalm-)?param[ \t]+' . CommentAnalyzer::TYPE_REGEX . '/'; - break; - - case self::FUNCTION_PARAM_VAR: - $regex = '/(\$[^ ]*)/'; - break; - - case self::CATCH_VAR: - $regex = '/(\$[^ ^\)]*)/'; - break; - - default: - throw new UnexpectedValueException('Unrecognised regex type ' . $this->regex_type); - } + $regex = match ($this->regex_type) { + self::VAR_TYPE => '/@(?:psalm-)?var[ \t]+' . CommentAnalyzer::TYPE_REGEX . '/', + self::FUNCTION_RETURN_TYPE => '/\\:\s+(\\??\s*[A-Za-z0-9_\\\\\[\]]+)/', + self::FUNCTION_PARAM_TYPE => '/^(\\??\s*[A-Za-z0-9_\\\\\[\]]+)\s/', + self::FUNCTION_PHPDOC_RETURN_TYPE => '/@(?:psalm-)?return[ \t]+' . CommentAnalyzer::TYPE_REGEX . '/', + self::FUNCTION_PHPDOC_METHOD => '/@(?:psalm-)?method[ \t]+(.*)/', + self::FUNCTION_PHPDOC_PARAM_TYPE => '/@(?:psalm-)?param[ \t]+' . CommentAnalyzer::TYPE_REGEX . '/', + self::FUNCTION_PARAM_VAR => '/(\$[^ ]*)/', + self::CATCH_VAR => '/(\$[^ ^\)]*)/', + default => throw new UnexpectedValueException('Unrecognised regex type ' . $this->regex_type), + }; $preview_snippet = mb_strcut( $file_contents, diff --git a/src/Psalm/Codebase.php b/src/Psalm/Codebase.php index 1e2e47498b7..dd549856f0a 100644 --- a/src/Psalm/Codebase.php +++ b/src/Psalm/Codebase.php @@ -71,7 +71,6 @@ use UnexpectedValueException; use function array_combine; -use function array_merge; use function array_pop; use function array_reverse; use function array_values; @@ -88,7 +87,9 @@ use function ksort; use function preg_match; use function preg_replace; +use function str_contains; use function str_replace; +use function str_starts_with; use function strlen; use function strpos; use function strrpos; @@ -100,8 +101,6 @@ final class Codebase { - public Config $config; - /** * A map of fully-qualified use declarations to the files * that reference them (keyed by filename) @@ -129,7 +128,7 @@ final class Codebase public StatementsProvider $statements_provider; - private Progress $progress; + private readonly Progress $progress; /** * @var array @@ -243,15 +242,13 @@ final class Codebase /** @internal */ public function __construct( - Config $config, + public Config $config, Providers $providers, ?Progress $progress = null, ) { if ($progress === null) { $progress = new VoidProgress(); } - - $this->config = $config; $this->file_storage_provider = $providers->file_storage_provider; $this->classlike_storage_provider = $providers->classlike_storage_provider; $this->progress = $progress; @@ -506,11 +503,11 @@ public function findReferencesToSymbol(string $symbol): array throw new UnexpectedValueException('Should not be checking references'); } - if (strpos($symbol, '::$') !== false) { + if (str_contains($symbol, '::$')) { return $this->findReferencesToProperty($symbol); } - if (strpos($symbol, '::') !== false) { + if (str_contains($symbol, '::')) { return $this->findReferencesToMethod($symbol); } @@ -848,7 +845,7 @@ public function invalidateInformationForFile(string $file_path): void try { $file_storage = $this->file_storage_provider->get($file_path); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return; } @@ -937,7 +934,7 @@ public function getMarkupContentForSymbolByReference( [, $symbol_name] = explode('::', $reference->symbol); //Class Property - if (strpos($reference->symbol, '$') !== false) { + if (str_contains($reference->symbol, '$')) { $property_id = (string) preg_replace('/^\\\\/', '', $reference->symbol); /** @psalm-suppress PossiblyUndefinedIntArrayOffset */ [$fq_class_name, $property_name] = explode('::$', $property_id); @@ -1033,7 +1030,7 @@ public function getMarkupContentForSymbolByReference( } //Procedural Variable - if (strpos($reference->symbol, '$') === 0) { + if (str_starts_with($reference->symbol, '$')) { $type = VariableFetchAnalyzer::getGlobalType($reference->symbol, $this->analysis_php_version_id); if (!$type->isMixed()) { return new PHPMarkdownContent( @@ -1054,7 +1051,7 @@ public function getMarkupContentForSymbolByReference( $storage->name, $storage->description, ); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { //continue on as normal } @@ -1151,7 +1148,7 @@ public function getSymbolLocationByReference(Reference $reference): ?CodeLocatio return $storage->location; } - if (strpos($reference->symbol, '$') !== false) { + if (str_contains($reference->symbol, '$')) { $storage = $this->properties->getStorage( $reference->symbol, ); @@ -1203,7 +1200,7 @@ public function getSymbolLocationByReference(Reference $reference): ?CodeLocatio error_log($e->getMessage()); return null; - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return null; } } @@ -1343,7 +1340,7 @@ public function getSignatureInformation( ): ?SignatureInformation { $signature_label = ''; $signature_documentation = null; - if (strpos($function_symbol, '::') !== false) { + if (str_contains($function_symbol, '::')) { /** @psalm-suppress ArgumentTypeCoercion */ $method_id = new MethodIdentifier(...explode('::', $function_symbol)); @@ -1372,7 +1369,7 @@ public function getSignatureInformation( $params = $function_storage->params; $signature_label = $function_storage->cased_name; $signature_documentation = $function_storage->description; - } catch (Exception $exception) { + } catch (Exception) { if (InternalCallMapHandler::inCallMap($function_symbol)) { $callables = InternalCallMapHandler::getCallablesFromCallMap($function_symbol); @@ -1605,7 +1602,7 @@ public function getCompletionItemsForClassishThing( ); } - $completion_items = array_merge($completion_items, array_values($pseudo_property_types)); + $completion_items = [...$completion_items, ...array_values($pseudo_property_types)]; foreach ($class_storage->declaring_property_ids as $property_name => $declaring_class) { $property_storage = $this->properties->getStorage( @@ -1671,7 +1668,7 @@ public function getCompletionItemsForPartialSymbol( foreach ($file_storage->classlikes_in_file as $fq_class_name => $_) { try { $class_storage = $this->classlike_storage_provider->get($fq_class_name); - } catch (Exception $e) { + } catch (Exception) { continue; } @@ -1746,7 +1743,7 @@ public function getCompletionItemsForPartialSymbol( try { $class_storage = $this->classlike_storage_provider->get($fq_class_name); $description = $class_storage->description; - } catch (Exception $e) { + } catch (Exception) { $description = null; } @@ -1786,14 +1783,14 @@ public function getCompletionItemsForPartialSymbol( } $in_namespace_map = false; foreach ($namespace_map as $namespace_name => $namespace_alias) { - if (strpos($function_lowercase, $namespace_name . '\\') === 0) { + if (str_starts_with($function_lowercase, $namespace_name . '\\')) { $function_name = $namespace_alias . '\\' . substr($function_name, strlen($namespace_name) + 1); $in_namespace_map = true; } } // If the function is not use'd, and it's not a global function // prepend it with a backslash. - if (!$in_namespace_map && strpos($function_name, '\\') !== false) { + if (!$in_namespace_map && str_contains($function_name, '\\')) { $function_name = '\\' . $function_name; } $completion_items[] = new CompletionItem( diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index d86d787c73b..b9a6d4d958c 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -69,7 +69,6 @@ use function flock; use function fopen; use function function_exists; -use function get_class; use function get_defined_constants; use function get_defined_functions; use function getcwd; @@ -98,7 +97,9 @@ use function scandir; use function sha1; use function simplexml_import_dom; +use function str_contains; use function str_replace; +use function str_starts_with; use function strlen; use function strpos; use function strrpos; @@ -130,10 +131,10 @@ class Config { private const DEFAULT_FILE_NAME = 'psalm.xml'; - public const CONFIG_NAMESPACE = 'https://getpsalm.org/schema/config'; - public const REPORT_INFO = 'info'; - public const REPORT_ERROR = 'error'; - public const REPORT_SUPPRESS = 'suppress'; + final public const CONFIG_NAMESPACE = 'https://getpsalm.org/schema/config'; + final public const REPORT_INFO = 'info'; + final public const REPORT_ERROR = 'error'; + final public const REPORT_SUPPRESS = 'suppress'; /** * @var array @@ -819,7 +820,7 @@ private static function processDeprecatedElement( assert($line > 0); $offset = self::lineNumberToByteOffset($file_contents, $line); - $element_start = strpos($file_contents, $deprecated_element_xml->localName, $offset) ?: 0; + $element_start = strpos($file_contents, (string) $deprecated_element_xml->localName, $offset) ?: 0; $element_end = $element_start + strlen($deprecated_element_xml->localName) - 1; $config->config_issues[] = new ConfigIssue( @@ -963,15 +964,15 @@ private static function fromXmlAndPaths( if (file_exists($composer_json_path)) { $composer_json_contents = file_get_contents($composer_json_path); assert($composer_json_contents !== false); - $composer_json = json_decode($composer_json_contents, true); + $composer_json = json_decode($composer_json_contents, true, 512, JSON_THROW_ON_ERROR); if (!is_array($composer_json)) { throw new UnexpectedValueException('Invalid composer.json at ' . $composer_json_path); } } $required_extensions = []; foreach (($composer_json["require"] ?? []) as $required => $_) { - if (strpos($required, "ext-") === 0) { - $required_extensions[strtolower(substr($required, 4))] = true; + if (str_starts_with((string) $required, "ext-")) { + $required_extensions[strtolower(substr((string) $required, 4))] = true; } } foreach ($required_extensions as $required_ext => $_) { @@ -1649,7 +1650,7 @@ public function reportIssueInFile(string $issue_type, string $file_path): bool try { $file_storage = $codebase->file_storage_provider->get($file_path); $dependent_files += $file_storage->required_by_file_paths; - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // do nothing } } @@ -1700,7 +1701,7 @@ public function trackTaintsInPath(string $file_path): bool public function getReportingLevelForIssue(CodeIssue $e): string { - $fqcn_parts = explode('\\', get_class($e)); + $fqcn_parts = explode('\\', $e::class); $issue_type = array_pop($fqcn_parts); $reporting_level = null; @@ -1765,17 +1766,17 @@ public static function getParentIssueType(string $issue_type): ?string return null; } - if (strpos($issue_type, 'Possibly') === 0) { + if (str_starts_with($issue_type, 'Possibly')) { $stripped_issue_type = (string) preg_replace('/^Possibly(False|Null)?/', '', $issue_type, 1); - if (strpos($stripped_issue_type, 'Invalid') === false && strpos($stripped_issue_type, 'Un') !== 0) { + if (!str_contains($stripped_issue_type, 'Invalid') && !str_starts_with($stripped_issue_type, 'Un')) { $stripped_issue_type = 'Invalid' . $stripped_issue_type; } return $stripped_issue_type; } - if (strpos($issue_type, 'Tainted') === 0) { + if (str_starts_with($issue_type, 'Tainted')) { return 'TaintedInput'; } @@ -2298,7 +2299,7 @@ public function visitComposerAutoloadFiles(ProjectAnalyzer $project_analyzer, ?P $codebase->classlikes->forgetMissingClassLikes(); $this->include_collector->runAndCollect( - [$this, 'requireAutoloader'], + $this->requireAutoloader(...), ); } @@ -2502,7 +2503,7 @@ public function getPHPVersionFromComposerJson(): ?string $composer_json_contents = file_get_contents($composer_json_path); assert($composer_json_contents !== false); $composer_json = json_decode($composer_json_contents, true, 512, JSON_THROW_ON_ERROR); - } catch (JsonException $e) { + } catch (JsonException) { $composer_json = null; } diff --git a/src/Psalm/Config/Creator.php b/src/Psalm/Config/Creator.php index aa52bee23e1..e0b2fd532bb 100644 --- a/src/Psalm/Config/Creator.php +++ b/src/Psalm/Config/Creator.php @@ -289,11 +289,7 @@ private static function guessPhpFileDirs(string $current_dir): array $nodes = []; /** @var string[] */ - $php_files = array_merge( - glob($current_dir . DIRECTORY_SEPARATOR . '*.php', GLOB_NOSORT) ?: [], - glob($current_dir . DIRECTORY_SEPARATOR . '**/*.php', GLOB_NOSORT) ?: [], - glob($current_dir . DIRECTORY_SEPARATOR . '**/**/*.php', GLOB_NOSORT) ?: [], - ); + $php_files = [...glob($current_dir . DIRECTORY_SEPARATOR . '*.php', GLOB_NOSORT) ?: [], ...glob($current_dir . DIRECTORY_SEPARATOR . '**/*.php', GLOB_NOSORT) ?: [], ...glob($current_dir . DIRECTORY_SEPARATOR . '**/**/*.php', GLOB_NOSORT) ?: []]; foreach ($php_files as $php_file) { $php_file = str_replace($current_dir . DIRECTORY_SEPARATOR, '', $php_file); diff --git a/src/Psalm/Config/FileFilter.php b/src/Psalm/Config/FileFilter.php index 4eb8c1a32f2..c351baee0dd 100644 --- a/src/Psalm/Config/FileFilter.php +++ b/src/Psalm/Config/FileFilter.php @@ -30,9 +30,10 @@ use function restore_error_handler; use function rtrim; use function set_error_handler; +use function str_contains; use function str_replace; +use function str_starts_with; use function stripos; -use function strpos; use function strtolower; use const DIRECTORY_SEPARATOR; @@ -90,8 +91,6 @@ class FileFilter */ protected array $files_lowercase = []; - protected bool $inclusive; - /** * @var array */ @@ -102,9 +101,8 @@ class FileFilter */ protected array $declare_strict_types = []; - public function __construct(bool $inclusive) + public function __construct(protected bool $inclusive) { - $this->inclusive = $inclusive; } /** @@ -134,7 +132,7 @@ public static function loadFromArray( $prospective_directory_path = $base_dir . DIRECTORY_SEPARATOR . $directory_path; } - if (strpos($prospective_directory_path, '*') !== false) { + if (str_contains($prospective_directory_path, '*')) { // Strip meaningless trailing recursive wildcard like "path/**/" or "path/**" $prospective_directory_path = (string) preg_replace( '#(\/\*\*)+\/?$#', @@ -257,7 +255,7 @@ public static function loadFromArray( $prospective_file_path = $base_dir . DIRECTORY_SEPARATOR . $file_path; } - if (strpos($prospective_file_path, '*') !== false) { + if (str_contains($prospective_file_path, '*')) { // Split by /**/, allow duplicated wildcards like "path/**/**/path" and any leading dir separator. /** @var non-empty-list $path_parts */ $path_parts = preg_split('#(\/|\\\)(\*\*\/)+#', $prospective_file_path); @@ -311,7 +309,7 @@ public static function loadFromArray( foreach ($config['referencedClass'] as $referenced_class) { $class_name = strtolower((string) ($referenced_class['name'] ?? '')); - if (strpos($class_name, '*') !== false) { + if (str_contains($class_name, '*')) { $regex = '/' . str_replace('*', '.*', str_replace('\\', '\\\\', $class_name)) . '/i'; $filter->fq_classlike_patterns[] = $regex; } else { @@ -522,7 +520,7 @@ public function allows(string $file_name, bool $case_sensitive = false): bool if ($this->inclusive) { foreach ($this->directories as $include_dir) { if ($case_sensitive) { - if (strpos($file_name, $include_dir) === 0) { + if (str_starts_with($file_name, $include_dir)) { return true; } } else { @@ -548,7 +546,7 @@ public function allows(string $file_name, bool $case_sensitive = false): bool // exclusive foreach ($this->directories as $exclude_dir) { if ($case_sensitive) { - if (strpos($file_name, $exclude_dir) === 0) { + if (str_starts_with($file_name, $exclude_dir)) { return false; } } else { diff --git a/src/Psalm/Config/ProjectFileFilter.php b/src/Psalm/Config/ProjectFileFilter.php index e3ffd4b20f0..2526413db04 100644 --- a/src/Psalm/Config/ProjectFileFilter.php +++ b/src/Psalm/Config/ProjectFileFilter.php @@ -7,8 +7,8 @@ use Psalm\Exception\ConfigException; use SimpleXMLElement; +use function str_starts_with; use function stripos; -use function strpos; /** @internal */ final class ProjectFileFilter extends FileFilter @@ -59,7 +59,7 @@ public function reportTypeStats(string $file_name, bool $case_sensitive = false) { foreach ($this->ignore_type_stats as $exclude_dir => $_) { if ($case_sensitive) { - if (strpos($file_name, $exclude_dir) === 0) { + if (str_starts_with($file_name, $exclude_dir)) { return false; } } else { @@ -76,7 +76,7 @@ public function useStrictTypes(string $file_name, bool $case_sensitive = false): { foreach ($this->declare_strict_types as $exclude_dir => $_) { if ($case_sensitive) { - if (strpos($file_name, $exclude_dir) === 0) { + if (str_starts_with($file_name, $exclude_dir)) { return true; } } else { diff --git a/src/Psalm/Context.php b/src/Psalm/Context.php index 084e0650b31..b09a704d2c2 100644 --- a/src/Psalm/Context.php +++ b/src/Psalm/Context.php @@ -30,6 +30,7 @@ use function preg_match; use function preg_quote; use function preg_replace; +use function str_contains; use function strpos; use function strtolower; @@ -148,12 +149,6 @@ final class Context public ?CodeLocation $include_location = null; - /** - * @var string|null - * The name of the current class. Null if outside a class. - */ - public ?string $self = null; - public ?string $parent = null; public bool $check_classes = true; @@ -332,9 +327,13 @@ final class Context public array $parent_remove_vars = []; /** @internal */ - public function __construct(?string $self = null) - { - $this->self = $self; + public function __construct( + /** + * @var string|null + * The name of the current class. Null if outside a class. + */ + public ?string $self = null, + ) { } public function __destruct() @@ -696,7 +695,7 @@ public function removeMutableObjectVars(bool $methods_only = false): void foreach ($this->vars_in_scope as $var_id => $type) { if ($type->has_mutations - && (strpos($var_id, '->') !== false || strpos($var_id, '::') !== false) + && (str_contains($var_id, '->') || str_contains($var_id, '::')) && (!$methods_only || strpos($var_id, '()')) ) { $vars_to_remove[] = $var_id; @@ -717,7 +716,7 @@ public function removeMutableObjectVars(bool $methods_only = false): void $abandon_clause = false; foreach (array_keys($clause->possibilities) as $key) { - if ((strpos($key, '->') !== false || strpos($key, '::') !== false) + if ((str_contains($key, '->') || str_contains($key, '::')) && (!$methods_only || strpos($key, '()')) ) { $abandon_clause = true; diff --git a/src/Psalm/DocComment.php b/src/Psalm/DocComment.php index 791f287066c..0a6b0cce668 100644 --- a/src/Psalm/DocComment.php +++ b/src/Psalm/DocComment.php @@ -12,8 +12,8 @@ use function explode; use function in_array; use function preg_match; +use function str_starts_with; use function strlen; -use function strpos; use function strspn; use function substr; use function trim; @@ -50,7 +50,7 @@ public static function parsePreservingLength(Doc $docblock): ParsedDocblock ); foreach ($parsed_docblock->tags as $special_key => $_) { - if (strpos($special_key, 'psalm-') === 0) { + if (str_starts_with($special_key, 'psalm-')) { $special_key = substr($special_key, 6); if (!in_array( diff --git a/src/Psalm/Exception/UnresolvableConstantException.php b/src/Psalm/Exception/UnresolvableConstantException.php index 175fe7b033e..1f18cf24842 100644 --- a/src/Psalm/Exception/UnresolvableConstantException.php +++ b/src/Psalm/Exception/UnresolvableConstantException.php @@ -8,13 +8,7 @@ final class UnresolvableConstantException extends Exception { - public string $class_name; - - public string $const_name; - - public function __construct(string $class_name, string $const_name) + public function __construct(public string $class_name, public string $const_name) { - $this->class_name = $class_name; - $this->const_name = $const_name; } } diff --git a/src/Psalm/FileBasedPluginAdapter.php b/src/Psalm/FileBasedPluginAdapter.php index 882e1b7d85b..0670e2ef1f8 100644 --- a/src/Psalm/FileBasedPluginAdapter.php +++ b/src/Psalm/FileBasedPluginAdapter.php @@ -22,21 +22,15 @@ /** @internal */ final class FileBasedPluginAdapter implements PluginEntryPointInterface { - private string $path; + private readonly string $path; - private Codebase $codebase; - - private Config $config; - - public function __construct(string $path, Config $config, Codebase $codebase) + public function __construct(string $path, private readonly Config $config, private Codebase $codebase) { if (!$path) { throw new UnexpectedValueException('$path cannot be empty'); } $this->path = $path; - $this->config = $config; - $this->codebase = $codebase; } public function __invoke(RegistrationInterface $registration, ?SimpleXMLElement $config = null): void diff --git a/src/Psalm/FileManipulation.php b/src/Psalm/FileManipulation.php index 56acda2c230..fbc8bcfca4c 100644 --- a/src/Psalm/FileManipulation.php +++ b/src/Psalm/FileManipulation.php @@ -12,28 +12,8 @@ final class FileManipulation { - public int $start; - - public int $end; - - public string $insertion_text; - - public bool $preserve_indentation; - - public bool $remove_trailing_newline; - - public function __construct( - int $start, - int $end, - string $insertion_text, - bool $preserve_indentation = false, - bool $remove_trailing_newline = false, - ) { - $this->start = $start; - $this->end = $end; - $this->insertion_text = $insertion_text; - $this->preserve_indentation = $preserve_indentation; - $this->remove_trailing_newline = $remove_trailing_newline; + public function __construct(public int $start, public int $end, public string $insertion_text, public bool $preserve_indentation = false, public bool $remove_trailing_newline = false) + { } public function getKey(): string diff --git a/src/Psalm/Internal/Analyzer/AlgebraAnalyzer.php b/src/Psalm/Internal/Analyzer/AlgebraAnalyzer.php index 71f22863d2d..1bc26151484 100644 --- a/src/Psalm/Internal/Analyzer/AlgebraAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/AlgebraAnalyzer.php @@ -45,7 +45,7 @@ public static function checkForParadox( ): void { try { $negated_formula2 = Algebra::negateFormula($formula_2); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { return; } diff --git a/src/Psalm/Internal/Analyzer/ClassAnalyzer.php b/src/Psalm/Internal/Analyzer/ClassAnalyzer.php index 3842dce767d..f6d03381690 100644 --- a/src/Psalm/Internal/Analyzer/ClassAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClassAnalyzer.php @@ -582,7 +582,7 @@ public function analyze( try { $trait_file_analyzer = $project_analyzer->getFileAnalyzerForClassLike($fq_trait_name); - } catch (Exception $e) { + } catch (Exception) { continue; } @@ -945,7 +945,7 @@ public static function addContextProperties( try { $docBlock = DocComment::parsePreservingLength($docComment); $suppressed = $docBlock->tags['psalm-suppress'] ?? []; - } catch (DocblockParseException $e) { + } catch (DocblockParseException) { // do nothing to keep original behavior } } @@ -2077,7 +2077,7 @@ private function checkImplementedInterfaces( try { $interface_storage = $classlike_storage_provider->get($fq_interface_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return false; } @@ -2111,7 +2111,7 @@ private function checkImplementedInterfaces( foreach ($storage->class_implements as $fq_interface_name_lc => $fq_interface_name) { try { $interface_storage = $classlike_storage_provider->get($fq_interface_name_lc); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return false; } @@ -2474,7 +2474,7 @@ private function checkParentClass( $code_location, $storage->template_type_extends_count[$parent_fq_class_name] ?? 0, ); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // do nothing } } diff --git a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php index cf54d72c3ab..98690b3795f 100644 --- a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php @@ -82,12 +82,8 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer 'unknown type' => true, ]; - protected PhpParser\Node\Stmt\ClassLike $class; - public FileAnalyzer $file_analyzer; - protected string $fq_class_name; - /** * The parent class */ @@ -95,12 +91,10 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer protected ClassLikeStorage $storage; - public function __construct(PhpParser\Node\Stmt\ClassLike $class, SourceAnalyzer $source, string $fq_class_name) + public function __construct(protected PhpParser\Node\Stmt\ClassLike $class, SourceAnalyzer $source, protected string $fq_class_name) { - $this->class = $class; $this->source = $source; $this->file_analyzer = $source->getFileAnalyzer(); - $this->fq_class_name = $fq_class_name; $codebase = $source->getCodebase(); $this->storage = $codebase->classlike_storage_provider->get($fq_class_name); } @@ -802,7 +796,7 @@ public static function getClassesForFile(Codebase $codebase, string $file_path): { try { return $codebase->file_storage_provider->get($file_path)->classlikes_in_file; - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return []; } } diff --git a/src/Psalm/Internal/Analyzer/ClassLikeNameOptions.php b/src/Psalm/Internal/Analyzer/ClassLikeNameOptions.php index d1fb0c95218..4c91c6b920b 100644 --- a/src/Psalm/Internal/Analyzer/ClassLikeNameOptions.php +++ b/src/Psalm/Internal/Analyzer/ClassLikeNameOptions.php @@ -9,31 +9,7 @@ */ final class ClassLikeNameOptions { - public bool $inferred; - - public bool $allow_trait; - - public bool $allow_interface; - - public bool $allow_enum; - - public bool $from_docblock; - - public bool $from_attribute; - - public function __construct( - bool $inferred = false, - bool $allow_trait = false, - bool $allow_interface = true, - bool $allow_enum = true, - bool $from_docblock = false, - bool $from_attribute = false, - ) { - $this->inferred = $inferred; - $this->allow_trait = $allow_trait; - $this->allow_interface = $allow_interface; - $this->allow_enum = $allow_enum; - $this->from_docblock = $from_docblock; - $this->from_attribute = $from_attribute; + public function __construct(public bool $inferred = false, public bool $allow_trait = false, public bool $allow_interface = true, public bool $allow_enum = true, public bool $from_docblock = false, public bool $from_attribute = false) + { } } diff --git a/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php b/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php index 34cd81bc0fb..f6f9d12aa53 100644 --- a/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php @@ -22,7 +22,7 @@ use function in_array; use function is_string; use function preg_match; -use function strpos; +use function str_starts_with; use function strtolower; /** @@ -104,7 +104,7 @@ public static function analyzeExpression( } foreach ($context->vars_in_scope as $var => $type) { - if (strpos($var, '$this->') === 0) { + if (str_starts_with($var, '$this->')) { $use_context->vars_in_scope[$var] = $type; } } @@ -122,7 +122,7 @@ public static function analyzeExpression( } foreach ($context->vars_possibly_in_scope as $var => $_) { - if (strpos($var, '$this->') === 0) { + if (str_starts_with($var, '$this->')) { $use_context->vars_possibly_in_scope[$var] = true; } } diff --git a/src/Psalm/Internal/Analyzer/CommentAnalyzer.php b/src/Psalm/Internal/Analyzer/CommentAnalyzer.php index aabd1747028..8f0264e7caf 100644 --- a/src/Psalm/Internal/Analyzer/CommentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/CommentAnalyzer.php @@ -27,7 +27,6 @@ use Psalm\Type\Union; use UnexpectedValueException; -use function array_merge; use function count; use function is_string; use function preg_match; @@ -139,7 +138,7 @@ public static function arrayToDocblocks( $template_type_map, $type_aliases, ); - } catch (TypeParseTreeException $e) { + } catch (TypeParseTreeException) { throw new DocblockParseException($line_parts[0] . ' is not a valid type'); } @@ -402,7 +401,7 @@ public static function splitDocLine(string $return_block): array $remaining = trim((string) preg_replace('@^[ \t]*\* *@m', ' ', substr($return_block, $i + 1))); if ($remaining) { - return array_merge([rtrim($type)], preg_split('/\s+/', $remaining) ?: []); + return [rtrim($type), ...preg_split('/\s+/', $remaining) ?: []]; } return [$type]; diff --git a/src/Psalm/Internal/Analyzer/DataFlowNodeData.php b/src/Psalm/Internal/Analyzer/DataFlowNodeData.php index 7f2e989a547..da99e343596 100644 --- a/src/Psalm/Internal/Analyzer/DataFlowNodeData.php +++ b/src/Psalm/Internal/Analyzer/DataFlowNodeData.php @@ -14,51 +14,7 @@ final class DataFlowNodeData { use ImmutableNonCloneableTrait; - public int $line_from; - - public int $line_to; - - public string $label; - - public string $file_name; - - public string $file_path; - - public string $snippet; - - public int $from; - - public int $to; - - public int $snippet_from; - - public int $column_from; - - public int $column_to; - - public function __construct( - string $label, - int $line_from, - int $line_to, - string $file_name, - string $file_path, - string $snippet, - int $from, - int $to, - int $snippet_from, - int $column_from, - int $column_to, - ) { - $this->label = $label; - $this->line_from = $line_from; - $this->line_to = $line_to; - $this->file_name = $file_name; - $this->file_path = $file_path; - $this->snippet = $snippet; - $this->from = $from; - $this->to = $to; - $this->snippet_from = $snippet_from; - $this->column_from = $column_from; - $this->column_to = $column_to; + public function __construct(public string $label, public int $line_from, public int $line_to, public string $file_name, public string $file_path, public string $snippet, public int $from, public int $to, public int $snippet_from, public int $column_from, public int $column_to) + { } } diff --git a/src/Psalm/Internal/Analyzer/FileAnalyzer.php b/src/Psalm/Internal/Analyzer/FileAnalyzer.php index 832bfecb59e..62aeac08f2f 100644 --- a/src/Psalm/Internal/Analyzer/FileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FileAnalyzer.php @@ -34,7 +34,7 @@ use function array_diff_key; use function array_keys; use function count; -use function strpos; +use function str_starts_with; use function strtolower; /** @@ -45,10 +45,6 @@ class FileAnalyzer extends SourceAnalyzer { use CanAlias; - protected string $file_name; - - protected string $file_path; - protected ?string $root_file_path = null; protected ?string $root_file_name = null; @@ -95,8 +91,6 @@ class FileAnalyzer extends SourceAnalyzer public ?Context $context = null; - public ProjectAnalyzer $project_analyzer; - public Codebase $codebase; private int $first_statement_offset = -1; @@ -105,12 +99,9 @@ class FileAnalyzer extends SourceAnalyzer private ?Union $return_type = null; - public function __construct(ProjectAnalyzer $project_analyzer, string $file_path, string $file_name) + public function __construct(public ProjectAnalyzer $project_analyzer, protected string $file_path, protected string $file_name) { $this->source = $this; - $this->file_path = $file_path; - $this->file_name = $file_name; - $this->project_analyzer = $project_analyzer; $this->codebase = $project_analyzer->getCodebase(); } @@ -148,7 +139,7 @@ public function analyze( try { $stmts = $codebase->getStatementsForFile($this->file_path); - } catch (PhpParser\Error $e) { + } catch (PhpParser\Error) { return; } @@ -395,13 +386,13 @@ public function getMethodMutations( $call_context->calling_method_id = $this_context->calling_method_id; foreach ($this_context->vars_possibly_in_scope as $var => $_) { - if (strpos($var, '$this->') === 0) { + if (str_starts_with($var, '$this->')) { $call_context->vars_possibly_in_scope[$var] = true; } } foreach ($this_context->vars_in_scope as $var => $type) { - if (strpos($var, '$this->') === 0) { + if (str_starts_with($var, '$this->')) { $call_context->vars_in_scope[$var] = $type; } } diff --git a/src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeAnalyzer.php b/src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeAnalyzer.php index bc571e03548..c38b73e8b4d 100644 --- a/src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeAnalyzer.php @@ -59,7 +59,7 @@ use function count; use function implode; use function in_array; -use function strpos; +use function str_starts_with; use function strtolower; /** @@ -127,7 +127,7 @@ public static function verifyReturnType( $is_to_string = $function instanceof ClassMethod && strtolower($function->name->name) === '__tostring'; if ($function instanceof ClassMethod - && strpos($function->name->name, '__') === 0 + && str_starts_with($function->name->name, '__') && !$is_to_string && !$return_type ) { diff --git a/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php b/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php index 16ccc996926..3844c7eb053 100644 --- a/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php @@ -79,6 +79,7 @@ use function md5; use function microtime; use function reset; +use function str_starts_with; use function strpos; use function strtolower; use function substr; @@ -91,11 +92,6 @@ */ abstract class FunctionLikeAnalyzer extends SourceAnalyzer { - /** - * @var TFunction - */ - protected Closure|Function_|ClassMethod|ArrowFunction $function; - protected Codebase $codebase; /** @@ -135,18 +131,14 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer */ public array $param_nodes = []; - protected FunctionLikeStorage $storage; - /** * @param TFunction $function */ - public function __construct($function, SourceAnalyzer $source, FunctionLikeStorage $storage) + public function __construct(protected Closure|Function_|ClassMethod|ArrowFunction $function, SourceAnalyzer $source, protected FunctionLikeStorage $storage) { - $this->function = $function; $this->source = $source; $this->suppressed_issues = $source->getSuppressedIssues(); $this->codebase = $source->getCodebase(); - $this->storage = $storage; } /** @@ -804,20 +796,17 @@ public function analyze( } if ($this->return_vars_possibly_in_scope !== null) { - $context->vars_possibly_in_scope = array_merge( - $context->vars_possibly_in_scope, - $this->return_vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$this->return_vars_possibly_in_scope]; } foreach ($context->vars_in_scope as $var => $_) { - if (strpos($var, '$this->') !== 0 && $var !== '$this') { + if (!str_starts_with($var, '$this->') && $var !== '$this') { $context->removePossibleReference($var); } } foreach ($context->vars_possibly_in_scope as $var => $_) { - if (strpos($var, '$this->') !== 0 && $var !== '$this') { + if (!str_starts_with($var, '$this->') && $var !== '$this') { unset($context->vars_possibly_in_scope[$var]); } } @@ -1534,10 +1523,7 @@ public function addReturnTypes(Context $context): void } if ($this->return_vars_possibly_in_scope !== null) { - $this->return_vars_possibly_in_scope = array_merge( - $context->vars_possibly_in_scope, - $this->return_vars_possibly_in_scope, - ); + $this->return_vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$this->return_vars_possibly_in_scope]; } else { $this->return_vars_possibly_in_scope = $context->vars_possibly_in_scope; } @@ -1624,7 +1610,7 @@ public function getFunctionLikeStorage(?StatementsAnalyzer $statements_analyzer try { return $codebase_methods->getStorage($method_id); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { $declaring_method_id = $codebase_methods->getDeclaringMethodId($method_id); if ($declaring_method_id === null) { @@ -2157,6 +2143,6 @@ private function detectPreviousUnusedArgumentPosition(FunctionLikeStorage $funct private function isIgnoredForUnusedParam(string $var_name): bool { - return strpos($var_name, '$_') === 0 || (strpos($var_name, '$unused') === 0 && $var_name !== '$unused'); + return str_starts_with($var_name, '$_') || (str_starts_with($var_name, '$unused') && $var_name !== '$unused'); } } diff --git a/src/Psalm/Internal/Analyzer/InterfaceAnalyzer.php b/src/Psalm/Internal/Analyzer/InterfaceAnalyzer.php index fc798e4433e..2a2ec630c34 100644 --- a/src/Psalm/Internal/Analyzer/InterfaceAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/InterfaceAnalyzer.php @@ -74,7 +74,7 @@ public function analyze(): void try { $extended_interface_storage = $codebase->classlike_storage_provider->get($extended_interface_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } diff --git a/src/Psalm/Internal/Analyzer/IssueData.php b/src/Psalm/Internal/Analyzer/IssueData.php index 9e90b2d9020..c8674fd8fa4 100644 --- a/src/Psalm/Internal/Analyzer/IssueData.php +++ b/src/Psalm/Internal/Analyzer/IssueData.php @@ -16,137 +16,68 @@ final class IssueData public const SEVERITY_INFO = 'info'; public const SEVERITY_ERROR = 'error'; - /** - * @var self::SEVERITY_* - */ - public string $severity; - - public int $line_from; - - public int $line_to; - - /** - * @readonly - */ - public string $type; - - /** - * @readonly - */ - public string $message; - - /** - * @readonly - */ - public string $file_name; - - /** - * @readonly - */ - public string $file_path; - - /** - * @readonly - */ - public string $snippet; - - /** - * @readonly - */ - public string $selected_text; - - public int $from; - - public int $to; - - public int $snippet_from; - - public int $snippet_to; - - /** - * @readonly - */ - public int $column_from; - - /** - * @readonly - */ - public int $column_to; - - public int $error_level; - - /** - * @readonly - */ - public int $shortcode; - /** * @readonly */ public string $link; - /** - * @var ?list - */ - public ?array $taint_trace = null; - - /** - * @var ?list - */ - public ?array $other_references = null; - - /** - * @readonly - */ - public ?string $dupe_key = null; - /** * @param self::SEVERITY_* $severity * @param ?list $taint_trace * @param ?list $other_references */ public function __construct( - string $severity, - int $line_from, - int $line_to, - string $type, - string $message, - string $file_name, - string $file_path, - string $snippet, - string $selected_text, - int $from, - int $to, - int $snippet_from, - int $snippet_to, - int $column_from, - int $column_to, - int $shortcode = 0, - int $error_level = -1, - ?array $taint_trace = null, - array $other_references = null, - ?string $dupe_key = null, + public string $severity, + public int $line_from, + public int $line_to, + /** + * @readonly + */ + public string $type, + /** + * @readonly + */ + public string $message, + /** + * @readonly + */ + public string $file_name, + /** + * @readonly + */ + public string $file_path, + /** + * @readonly + */ + public string $snippet, + /** + * @readonly + */ + public string $selected_text, + public int $from, + public int $to, + public int $snippet_from, + public int $snippet_to, + /** + * @readonly + */ + public int $column_from, + /** + * @readonly + */ + public int $column_to, + /** + * @readonly + */ + public int $shortcode = 0, + public int $error_level = -1, + public ?array $taint_trace = null, + public ?array $other_references = null, + /** + * @readonly + */ + public ?string $dupe_key = null, ) { - $this->severity = $severity; - $this->line_from = $line_from; - $this->line_to = $line_to; - $this->type = $type; - $this->message = $message; - $this->file_name = $file_name; - $this->file_path = $file_path; - $this->snippet = $snippet; - $this->selected_text = $selected_text; - $this->from = $from; - $this->to = $to; - $this->snippet_from = $snippet_from; - $this->snippet_to = $snippet_to; - $this->column_from = $column_from; - $this->column_to = $column_to; - $this->shortcode = $shortcode; - $this->error_level = $error_level; $this->link = $shortcode ? 'https://psalm.dev/' . str_pad((string) $shortcode, 3, "0", STR_PAD_LEFT) : ''; - $this->taint_trace = $taint_trace; - $this->other_references = $other_references; - $this->dupe_key = $dupe_key; } } diff --git a/src/Psalm/Internal/Analyzer/MethodComparator.php b/src/Psalm/Internal/Analyzer/MethodComparator.php index 1a4b01f5fbd..b9477ec48a1 100644 --- a/src/Psalm/Internal/Analyzer/MethodComparator.php +++ b/src/Psalm/Internal/Analyzer/MethodComparator.php @@ -40,7 +40,7 @@ use function array_filter; use function in_array; -use function strpos; +use function str_starts_with; use function strtolower; /** @@ -438,7 +438,7 @@ private static function compareMethodParams( && $implementer_classlike_storage->user_defined && $implementer_param->location && $guide_method_storage->cased_name - && strpos($guide_method_storage->cased_name, '__') !== 0 + && !str_starts_with($guide_method_storage->cased_name, '__') && $config->isInProjectDirs( $implementer_param->location->file_path, ) @@ -732,7 +732,7 @@ private static function compareMethodDocblockParams( $builder = $implementer_method_storage_param_type->getBuilder(); foreach ($builder->getAtomicTypes() as $k => $t) { if ($t instanceof TTemplateParam - && strpos($t->defining_class, 'fn-') === 0 + && str_starts_with($t->defining_class, 'fn-') ) { $builder->removeType($k); @@ -746,7 +746,7 @@ private static function compareMethodDocblockParams( $builder = $guide_method_storage_param_type->getBuilder(); foreach ($builder->getAtomicTypes() as $k => $t) { if ($t instanceof TTemplateParam - && strpos($t->defining_class, 'fn-') === 0 + && str_starts_with($t->defining_class, 'fn-') ) { $builder->removeType($k); diff --git a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php index 6974a4c45e9..a6bac10d51a 100644 --- a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php @@ -28,15 +28,7 @@ final class NamespaceAnalyzer extends SourceAnalyzer { use CanAlias; - /** - * @var FileAnalyzer - * @psalm-suppress NonInvariantDocblockPropertyType - */ - protected SourceAnalyzer $source; - - private Namespace_ $namespace; - - private string $namespace_name; + private readonly string $namespace_name; /** * A lookup table for public namespace constants @@ -45,10 +37,12 @@ final class NamespaceAnalyzer extends SourceAnalyzer */ protected static array $public_namespace_constants = []; - public function __construct(Namespace_ $namespace, FileAnalyzer $source) - { - $this->source = $source; - $this->namespace = $namespace; + public function __construct( + private readonly Namespace_ $namespace, /** + * @psalm-suppress NonInvariantDocblockPropertyType + */ + protected SourceAnalyzer $source, + ) { $this->namespace_name = $this->namespace->name ? $this->namespace->name->toString() : ''; } diff --git a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index 2999499f382..c4ff79c024f 100644 --- a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -83,6 +83,8 @@ use function preg_match; use function rename; use function sprintf; +use function str_ends_with; +use function str_starts_with; use function strlen; use function strpos; use function strtolower; @@ -104,7 +106,7 @@ final class ProjectAnalyzer /** * Cached config */ - private Config $config; + private readonly Config $config; public static ProjectAnalyzer $instance; @@ -113,15 +115,15 @@ final class ProjectAnalyzer */ private Codebase $codebase; - private FileProvider $file_provider; + private readonly FileProvider $file_provider; - private ClassLikeStorageProvider $classlike_storage_provider; + private readonly ClassLikeStorageProvider $classlike_storage_provider; private ?ParserCacheProvider $parser_cache_provider = null; public ?ProjectCacheProvider $project_cache_provider = null; - private FileReferenceProvider $file_reference_provider; + private readonly FileReferenceProvider $file_reference_provider; public Progress $progress; @@ -131,8 +133,6 @@ final class ProjectAnalyzer public bool $show_issues = true; - public int $threads; - /** * @var array */ @@ -168,13 +168,6 @@ final class ProjectAnalyzer */ private array $to_refactor = []; - public ?ReportOptions $stdout_report_options = null; - - /** - * @var array - */ - public array $generated_report_options; - /** * @var array> */ @@ -212,9 +205,9 @@ final class ProjectAnalyzer public function __construct( Config $config, Providers $providers, - ?ReportOptions $stdout_report_options = null, - array $generated_report_options = [], - int $threads = 1, + public ?ReportOptions $stdout_report_options = null, + public array $generated_report_options = [], + public int $threads = 1, ?Progress $progress = null, ?Codebase $codebase = null, ) { @@ -237,16 +230,12 @@ public function __construct( $this->file_reference_provider = $providers->file_reference_provider; $this->progress = $progress; - $this->threads = $threads; $this->config = $config; $this->clearCacheDirectoryIfConfigOrComposerLockfileChanged(); $this->codebase = $codebase; - $this->stdout_report_options = $stdout_report_options; - $this->generated_report_options = $generated_report_options; - $this->config->processPluginFileExtensions($this); $file_extensions = $this->config->getFileExtensions(); @@ -254,7 +243,7 @@ public function __construct( $file_paths = $this->file_provider->getFilesInDir( $dir_name, $file_extensions, - [$this->config, 'isInProjectDirs'], + $this->config->isInProjectDirs(...), ); foreach ($file_paths as $file_path) { @@ -266,7 +255,7 @@ public function __construct( $file_paths = $this->file_provider->getFilesInDir( $dir_name, $file_extensions, - [$this->config, 'isInExtraDirs'], + $this->config->isInExtraDirs(...), ); foreach ($file_paths as $file_path) { @@ -353,7 +342,7 @@ public static function getFileReportOptions(array $report_file_paths, bool $show foreach ($report_file_paths as $report_file_path) { foreach ($mapping as $extension => $type) { - if (substr($report_file_path, -strlen($extension)) === $extension) { + if (str_ends_with($report_file_path, $extension)) { $o = new ReportOptions(); $o->format = $type; @@ -612,7 +601,7 @@ public function interpretRefactors(): void && $destination_pos === (strlen($destination) - 1) ) { foreach ($this->codebase->classlike_storage_provider->getAll() as $class_storage) { - if (strpos($source, substr($class_storage->name, 0, $source_pos)) === 0) { + if (str_starts_with($source, substr($class_storage->name, 0, $source_pos))) { $this->to_refactor[$class_storage->name] = substr($destination, 0, -1) . substr($class_storage->name, $source_pos); } @@ -938,7 +927,7 @@ public function checkDir(string $dir_name): void private function checkDirWithConfig(string $dir_name, Config $config, bool $allow_non_project_files = false): void { $file_extensions = $config->getFileExtensions(); - $filter = $allow_non_project_files ? null : [$this->config, 'isInProjectDirs']; + $filter = $allow_non_project_files ? null : $this->config->isInProjectDirs(...); $file_paths = $this->file_provider->getFilesInDir( $dir_name, diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php index 236b8a1f791..d23b31785b2 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php @@ -20,7 +20,6 @@ use function array_diff; use function array_filter; use function array_keys; -use function array_merge; use function array_values; use function in_array; use function preg_match; @@ -158,10 +157,7 @@ static function (Clause $c) use ($mixed_var_ids): bool { $do_context->loop_scope = null; - $context->vars_possibly_in_scope = array_merge( - $context->vars_possibly_in_scope, - $do_context->vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$do_context->vars_possibly_in_scope]; if ($context->collect_exceptions) { $context->mergeExceptions($inner_loop_context); diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php index ad1b5a601de..96c67cda896 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php @@ -170,10 +170,7 @@ public static function analyze( $for_context->loop_scope = null; if ($can_leave_loop) { - $context->vars_possibly_in_scope = array_merge( - $context->vars_possibly_in_scope, - $for_context->vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$for_context->vars_possibly_in_scope]; } elseif ($pre_context) { $context->vars_possibly_in_scope = $pre_context->vars_possibly_in_scope; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php index 54fd5391bcd..5843cb1c3e3 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php @@ -63,7 +63,6 @@ use function array_keys; use function array_map; -use function array_merge; use function array_search; use function array_values; use function assert; @@ -386,10 +385,7 @@ public static function analyze( $foreach_context->loop_scope = null; - $context->vars_possibly_in_scope = array_merge( - $foreach_context->vars_possibly_in_scope, - $context->vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$foreach_context->vars_possibly_in_scope, ...$context->vars_possibly_in_scope]; if ($context->collect_exceptions) { $context->mergeExceptions($foreach_context); @@ -549,10 +545,7 @@ public static function checkIteratorType( } } elseif ($iterator_atomic_type instanceof TIterable) { if ($iterator_atomic_type->extra_types) { - $iterator_atomic_types = array_merge( - [$iterator_atomic_type->setIntersectionTypes([])], - $iterator_atomic_type->extra_types, - ); + $iterator_atomic_types = [$iterator_atomic_type->setIntersectionTypes([]), ...$iterator_atomic_type->extra_types]; } else { $iterator_atomic_types = [$iterator_atomic_type]; } @@ -732,10 +725,7 @@ public static function handleIterable( bool &$has_valid_iterator, ): void { if ($iterator_atomic_type->extra_types) { - $iterator_atomic_types = array_merge( - [$iterator_atomic_type->setIntersectionTypes([])], - $iterator_atomic_type->extra_types, - ); + $iterator_atomic_types = [$iterator_atomic_type->setIntersectionTypes([]), ...$iterator_atomic_type->extra_types]; } else { $iterator_atomic_types = [$iterator_atomic_type]; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php index 843bbbce0de..00a588f5dfd 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php @@ -219,7 +219,7 @@ public static function analyze( // get all the var ids that were referenced in the conditional, but not assigned in it $cond_referenced_var_ids = array_diff_key($cond_referenced_var_ids, $assigned_in_conditional_var_ids); - $cond_referenced_var_ids = array_merge($newish_var_ids, $cond_referenced_var_ids); + $cond_referenced_var_ids = [...$newish_var_ids, ...$cond_referenced_var_ids]; return new IfConditionalScope( $if_context, diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php index f33293ca9bc..c89173b0371 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php @@ -82,7 +82,7 @@ public static function analyze( foreach ($changed_var_ids as $changed_var_id => $_) { foreach ($else_context->vars_in_scope as $var_id => $_) { - if (preg_match('/' . preg_quote($changed_var_id, '/') . '[\]\[\-]/', $var_id) + if (preg_match('/' . preg_quote((string) $changed_var_id, '/') . '[\]\[\-]/', $var_id) && !array_key_exists($var_id, $changed_var_ids) ) { $else_context->removePossibleReference($var_id); @@ -200,22 +200,13 @@ public static function analyze( if ($has_leaving_statements) { if ($else_context->loop_scope) { if (!$has_continue_statement && !$has_break_statement) { - $if_scope->new_vars_possibly_in_scope = array_merge( - $vars_possibly_in_scope, - $if_scope->new_vars_possibly_in_scope, - ); + $if_scope->new_vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; } - $else_context->loop_scope->vars_possibly_in_scope = array_merge( - $vars_possibly_in_scope, - $else_context->loop_scope->vars_possibly_in_scope, - ); + $else_context->loop_scope->vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$else_context->loop_scope->vars_possibly_in_scope]; } } else { - $if_scope->new_vars_possibly_in_scope = array_merge( - $vars_possibly_in_scope, - $if_scope->new_vars_possibly_in_scope, - ); + $if_scope->new_vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; $if_scope->possibly_assigned_var_ids = array_merge( $possibly_assigned_var_ids, diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php index 4a7769247b2..af3618d3024 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php @@ -188,7 +188,7 @@ public static function analyze( $negated_elseif_types = Algebra::getTruthsFromFormula( Algebra::negateFormula($elseif_clauses), ); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $reconcilable_elseif_types = []; $negated_elseif_types = []; } @@ -241,7 +241,7 @@ public static function analyze( foreach ($newly_reconciled_var_ids as $changed_var_id => $_) { foreach ($elseif_context->vars_in_scope as $var_id => $_) { - if (preg_match('/' . preg_quote($changed_var_id, '/') . '[\]\[\-]/', $var_id) + if (preg_match('/' . preg_quote((string) $changed_var_id, '/') . '[\]\[\-]/', $var_id) && !array_key_exists($var_id, $newly_reconciled_var_ids) && !array_key_exists($var_id, $cond_referenced_var_ids) ) { @@ -373,25 +373,16 @@ public static function analyze( if ($has_leaving_statements && $elseif_context->loop_scope) { if (!$has_continue_statement && !$has_break_statement) { - $if_scope->new_vars_possibly_in_scope = array_merge( - $vars_possibly_in_scope, - $if_scope->new_vars_possibly_in_scope, - ); + $if_scope->new_vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; $if_scope->possibly_assigned_var_ids = array_merge( $possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids, ); } - $elseif_context->loop_scope->vars_possibly_in_scope = array_merge( - $vars_possibly_in_scope, - $elseif_context->loop_scope->vars_possibly_in_scope, - ); + $elseif_context->loop_scope->vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$elseif_context->loop_scope->vars_possibly_in_scope]; } elseif (!$has_leaving_statements) { - $if_scope->new_vars_possibly_in_scope = array_merge( - $vars_possibly_in_scope, - $if_scope->new_vars_possibly_in_scope, - ); + $if_scope->new_vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; $if_scope->possibly_assigned_var_ids = array_merge( $possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids, @@ -407,7 +398,7 @@ public static function analyze( $if_scope->negated_clauses = Algebra::simplifyCNF( [...$if_scope->negated_clauses, ...Algebra::negateFormula($elseif_clauses)], ); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $if_scope->negated_clauses = []; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php index 2168ed3f956..932ad108202 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php @@ -131,7 +131,7 @@ public static function analyze( foreach ($changed_var_ids as $changed_var_id => $_) { foreach ($if_context->vars_in_scope as $var_id => $_) { - if (preg_match('/' . preg_quote($changed_var_id, '/') . '[\]\[\-]/', $var_id) + if (preg_match('/' . preg_quote((string) $changed_var_id, '/') . '[\]\[\-]/', $var_id) && !array_key_exists($var_id, $changed_var_ids) && !array_key_exists($var_id, $cond_referenced_var_ids) ) { @@ -146,10 +146,7 @@ public static function analyze( $if_context->reconciled_expression_clauses = []; - $outer_context->vars_possibly_in_scope = array_merge( - $if_context->vars_possibly_in_scope, - $outer_context->vars_possibly_in_scope, - ); + $outer_context->vars_possibly_in_scope = [...$if_context->vars_possibly_in_scope, ...$outer_context->vars_possibly_in_scope]; $old_if_context = clone $if_context; @@ -308,10 +305,7 @@ public static function analyze( $if_scope->new_vars_possibly_in_scope = $vars_possibly_in_scope; } - $if_context->loop_scope->vars_possibly_in_scope = array_merge( - $vars_possibly_in_scope, - $if_context->loop_scope->vars_possibly_in_scope, - ); + $if_context->loop_scope->vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_context->loop_scope->vars_possibly_in_scope]; } elseif (!$has_leaving_statements) { $if_scope->new_vars_possibly_in_scope = $vars_possibly_in_scope; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php index 273842a3722..cfbe2a6928f 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php @@ -112,7 +112,7 @@ public static function analyze( // this is the context for stuff that happens after the `if` block $post_if_context = $if_conditional_scope->post_if_context; $assigned_in_conditional_var_ids = $if_conditional_scope->assigned_in_conditional_var_ids; - } catch (ScopeAnalysisException $e) { + } catch (ScopeAnalysisException) { return false; } @@ -202,7 +202,7 @@ public static function analyze( try { $if_scope->negated_clauses = Algebra::negateFormula($if_clauses); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { try { $if_scope->negated_clauses = FormulaGenerator::getFormula( $cond_object_id, @@ -213,7 +213,7 @@ public static function analyze( $codebase, false, ); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $if_scope->negated_clauses = []; } } @@ -363,15 +363,9 @@ public static function analyze( ); } - $context->vars_possibly_in_scope = array_merge( - $context->vars_possibly_in_scope, - $if_scope->new_vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; - $context->possibly_assigned_var_ids = array_merge( - $context->possibly_assigned_var_ids, - $if_scope->possibly_assigned_var_ids ?: [], - ); + $context->possibly_assigned_var_ids = [...$context->possibly_assigned_var_ids, ...$if_scope->possibly_assigned_var_ids ?: []]; // vars can only be defined/redefined if there was an else (defined in every block) $context->assigned_var_ids = array_merge( diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php index c3a7648aafc..e0705a0cac4 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php @@ -139,10 +139,7 @@ public static function analyze( } } - $loop_parent_context->vars_possibly_in_scope = array_merge( - $continue_context->vars_possibly_in_scope, - $loop_parent_context->vars_possibly_in_scope, - ); + $loop_parent_context->vars_possibly_in_scope = [...$continue_context->vars_possibly_in_scope, ...$loop_parent_context->vars_possibly_in_scope]; } else { $original_parent_context = clone $loop_parent_context; @@ -270,10 +267,7 @@ public static function analyze( $continue_context->has_returned = false; - $loop_parent_context->vars_possibly_in_scope = array_merge( - $continue_context->vars_possibly_in_scope, - $loop_parent_context->vars_possibly_in_scope, - ); + $loop_parent_context->vars_possibly_in_scope = [...$continue_context->vars_possibly_in_scope, ...$loop_parent_context->vars_possibly_in_scope]; // if there are no changes to the types, no need to re-examine if (!$has_changes) { @@ -442,10 +436,7 @@ public static function analyze( $loop_parent_context->removeVarFromConflictingClauses($var_id); } else { $loop_parent_context->vars_in_scope[$var_id] = - $loop_parent_context->vars_in_scope[$var_id]->setParentNodes(array_merge( - $loop_parent_context->vars_in_scope[$var_id]->parent_nodes, - $continue_context->vars_in_scope[$var_id]->parent_nodes, - )) + $loop_parent_context->vars_in_scope[$var_id]->setParentNodes([...$loop_parent_context->vars_in_scope[$var_id]->parent_nodes, ...$continue_context->vars_in_scope[$var_id]->parent_nodes]) ; } } @@ -457,7 +448,7 @@ public static function analyze( try { $negated_pre_condition_clauses = Algebra::negateFormula(array_merge(...$pre_condition_clauses)); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $negated_pre_condition_clauses = []; } @@ -556,10 +547,7 @@ private static function updateLoopScopeContexts( } // merge vars possibly in scope at the end of each loop - $loop_context->vars_possibly_in_scope = array_merge( - $loop_context->vars_possibly_in_scope, - $loop_scope->vars_possibly_in_scope, - ); + $loop_context->vars_possibly_in_scope = [...$loop_context->vars_possibly_in_scope, ...$loop_scope->vars_possibly_in_scope]; } /** diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php index e5dfacd83d7..c3f5bc4f9ec 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php @@ -219,10 +219,7 @@ public static function analyze( $context->assigned_var_ids += $switch_scope->new_assigned_var_ids; } - $context->vars_possibly_in_scope = array_merge( - $context->vars_possibly_in_scope, - $switch_scope->new_vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$switch_scope->new_vars_possibly_in_scope]; //a switch can't return in all options without a default $context->has_returned = $all_options_returned && $has_default; diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php index 7e1dbdd3da0..a5a9f51e542 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php @@ -49,7 +49,7 @@ use function in_array; use function is_string; use function spl_object_id; -use function strpos; +use function str_starts_with; use function substr; /** @@ -92,7 +92,7 @@ public static function analyze( $fake_switch_condition = false; - if ($switch_var_id && strpos($switch_var_id, '$__tmp_switch__') === 0) { + if ($switch_var_id && str_starts_with($switch_var_id, '$__tmp_switch__')) { $switch_condition = new VirtualVariable( substr($switch_var_id, 1), $stmt->cond->getAttributes(), @@ -439,7 +439,7 @@ public static function analyze( if ($case_clauses && $case_equality_expr) { try { $negated_case_clauses = Algebra::negateFormula($case_clauses); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $case_equality_expr_id = spl_object_id($case_equality_expr); try { @@ -453,7 +453,7 @@ public static function analyze( false, false, ); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $negated_case_clauses = []; } } @@ -636,13 +636,10 @@ private static function handleNonReturningCase( } } - $switch_scope->new_vars_possibly_in_scope = array_merge( - array_diff_key( - $case_context->vars_possibly_in_scope, - $context->vars_possibly_in_scope, - ), - $switch_scope->new_vars_possibly_in_scope, - ); + $switch_scope->new_vars_possibly_in_scope = [...array_diff_key( + $case_context->vars_possibly_in_scope, + $context->vars_possibly_in_scope, + ), ...$switch_scope->new_vars_possibly_in_scope]; } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php index 9222f3109a7..eac73b50d57 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php @@ -239,7 +239,7 @@ public static function analyze( $fq_catch_class_lower = strtolower($fq_catch_class); foreach ($catch_context->possibly_thrown_exceptions as $exception_fqcln => $_) { - $exception_fqcln_lower = strtolower($exception_fqcln); + $exception_fqcln_lower = strtolower((string) $exception_fqcln); if ($exception_fqcln_lower === $fq_catch_class_lower || ($codebase->classExists($exception_fqcln) diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php index f992eb7a489..694515eb921 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php @@ -12,7 +12,6 @@ use Psalm\Type; use UnexpectedValueException; -use function array_merge; use function in_array; /** @@ -104,10 +103,7 @@ public static function analyze( $while_context->loop_scope = null; if ($can_leave_loop) { - $context->vars_possibly_in_scope = array_merge( - $context->vars_possibly_in_scope, - $while_context->vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$while_context->vars_possibly_in_scope]; } elseif ($pre_context) { $context->vars_possibly_in_scope = $pre_context->vars_possibly_in_scope; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php index 16ea3e83561..560305843d4 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php @@ -109,7 +109,9 @@ use function is_numeric; use function is_string; use function sprintf; +use function str_ends_with; use function str_replace; +use function str_starts_with; use function strpos; use function strtolower; use function substr; @@ -1015,7 +1017,7 @@ protected static function processCustomAssertion( $if_types[$var_id] = [[$assertion->rule[0]]]; } } elseif (is_string($assertion->var_id)) { - $is_function = substr($assertion->var_id, -2) === '()'; + $is_function = str_ends_with($assertion->var_id, '()'); $exploded_id = explode('->', $assertion->var_id); $var_id = $exploded_id[0] ?? null; $property = $exploded_id[1] ?? null; @@ -1071,7 +1073,7 @@ protected static function processCustomAssertion( } elseif (!$expr instanceof PhpParser\Node\Expr\FuncCall) { $assertion_var_id = $assertion->var_id; - if (strpos($assertion_var_id, 'self::') === 0) { + if (str_starts_with($assertion_var_id, 'self::')) { $assertion_var_id = $this_class_name.'::'.substr($assertion_var_id, 6); } } else { @@ -1145,7 +1147,7 @@ protected static function processCustomAssertion( $if_types[$var_id] = [[$assertion->rule[0]->getNegation()]]; } } elseif (is_string($assertion->var_id)) { - $is_function = substr($assertion->var_id, -2) === '()'; + $is_function = str_ends_with($assertion->var_id, '()'); $exploded_id = explode('->', $assertion->var_id); $var_id = $exploded_id[0] ?? null; $property = $exploded_id[1] ?? null; @@ -1202,7 +1204,7 @@ protected static function processCustomAssertion( $if_types[$assertion_var_id] = [[$rule]]; } elseif (!$expr instanceof PhpParser\Node\Expr\FuncCall) { $var_id = $assertion->var_id; - if (strpos($var_id, 'self::') === 0) { + if (str_starts_with($var_id, 'self::')) { $var_id = $this_class_name.'::'.substr($var_id, 6); } $if_types[$var_id] = [[$assertion->rule[0]->getNegation()]]; @@ -1857,44 +1859,24 @@ protected static function hasIsACheck( private static function getIsAssertion(string $function_name): ?Assertion { - switch ($function_name) { - case 'is_string': - return new IsType(new Atomic\TString()); - case 'is_int': - case 'is_integer': - case 'is_long': - return new IsType(new Atomic\TInt()); - case 'is_float': - case 'is_double': - case 'is_real': - return new IsType(new Atomic\TFloat()); - case 'is_scalar': - return new IsType(new Atomic\TScalar()); - case 'is_bool': - return new IsType(new Atomic\TBool()); - case 'is_resource': - return new IsType(new Atomic\TResource()); - case 'is_object': - return new IsType(new Atomic\TObject()); - case 'array_is_list': - return new IsType(Type::getListAtomic(Type::getMixed())); - case 'is_array': - return new IsType(new Atomic\TArray([Type::getArrayKey(), Type::getMixed()])); - case 'is_numeric': - return new IsType(new Atomic\TNumeric()); - case 'is_null': - return new IsType(new Atomic\TNull()); - case 'is_iterable': - return new IsType(new Atomic\TIterable()); - case 'is_countable': - return new IsCountable(); - case 'ctype_digit': - return new IsType(new Atomic\TNumericString); - case 'ctype_lower': - return new IsType(new Atomic\TNonEmptyLowercaseString); - } - - return null; + return match ($function_name) { + 'is_string' => new IsType(new Atomic\TString()), + 'is_int', 'is_integer', 'is_long' => new IsType(new Atomic\TInt()), + 'is_float', 'is_double', 'is_real' => new IsType(new Atomic\TFloat()), + 'is_scalar' => new IsType(new Atomic\TScalar()), + 'is_bool' => new IsType(new Atomic\TBool()), + 'is_resource' => new IsType(new Atomic\TResource()), + 'is_object' => new IsType(new Atomic\TObject()), + 'array_is_list' => new IsType(Type::getListAtomic(Type::getMixed())), + 'is_array' => new IsType(new Atomic\TArray([Type::getArrayKey(), Type::getMixed()])), + 'is_numeric' => new IsType(new Atomic\TNumeric()), + 'is_null' => new IsType(new Atomic\TNull()), + 'is_iterable' => new IsType(new Atomic\TIterable()), + 'is_countable' => new IsCountable(), + 'ctype_digit' => new IsType(new Atomic\TNumericString), + 'ctype_lower' => new IsType(new Atomic\TNonEmptyLowercaseString), + default => null, + }; } /** @@ -2531,7 +2513,7 @@ private static function getGettypeInequalityAssertions( $if_types[$var_name] = [[new IsNotIdentical(new TObject())]]; } elseif ($var_type === 'resource (closed)') { $if_types[$var_name] = [[new IsNotType(new TClosedResource())]]; - } elseif (strpos($var_type, 'resource (') === 0) { + } elseif (str_starts_with($var_type, 'resource (')) { $if_types[$var_name] = [[new IsNotIdentical(new TResource())]]; } else { $if_types[$var_name] = [[new IsNotType(Atomic::create($var_type))]]; @@ -2589,7 +2571,7 @@ private static function getGetdebugTypeInequalityAssertions( $if_types[$var_name] = [[new IsNotIdentical(new TObject())]]; } elseif ($var_type === 'resource (closed)') { $if_types[$var_name] = [[new IsNotType(new TClosedResource())]]; - } elseif (strpos($var_type, 'resource (') === 0) { + } elseif (str_starts_with($var_type, 'resource (')) { $if_types[$var_name] = [[new IsNotIdentical(new TResource())]]; } else { $if_types[$var_name] = [[new IsNotType(Atomic::create($var_type))]]; @@ -3244,7 +3226,7 @@ private static function getGettypeEqualityAssertions( $if_types[$var_name] = [[new IsIdentical(new TObject())]]; } elseif ($var_type === 'resource (closed)') { $if_types[$var_name] = [[new IsType(new TClosedResource())]]; - } elseif (strpos($var_type, 'resource (') === 0) { + } elseif (str_starts_with($var_type, 'resource (')) { $if_types[$var_name] = [[new IsIdentical(new TResource())]]; } elseif ($var_type === 'integer') { $if_types[$var_name] = [[new IsType(new Atomic\TInt())]]; @@ -3308,7 +3290,7 @@ private static function getGetdebugtypeEqualityAssertions( $if_types[$var_name] = [[new IsIdentical(new TObject())]]; } elseif ($var_type === 'resource (closed)') { $if_types[$var_name] = [[new IsType(new TClosedResource())]]; - } elseif (strpos($var_type, 'resource (') === 0) { + } elseif (str_starts_with($var_type, 'resource (')) { $if_types[$var_name] = [[new IsIdentical(new TResource())]]; } elseif ($var_type === 'integer') { $if_types[$var_name] = [[new IsType(new Atomic\TInt())]]; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php index 3a47c43d894..20bd245c4a0 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php @@ -49,8 +49,8 @@ use function in_array; use function is_string; use function preg_match; +use function str_contains; use function strlen; -use function strpos; /** * @internal @@ -510,7 +510,7 @@ private static function updateArrayAssignmentChildType( } if ($parent_var_id && ($parent_type = $context->vars_in_scope[$parent_var_id] ?? null)) { - if ($offset_already_existed && $parent_type->hasList() && strpos($parent_var_id, '[') === false) { + if ($offset_already_existed && $parent_type->hasList() && !str_contains($parent_var_id, '[')) { $array_atomic_type_list = $value_type; } elseif ($parent_type->hasClassStringMap() && $key_type diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/AssignedProperty.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/AssignedProperty.php index 7a35ff2c069..2f55918ffec 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/AssignedProperty.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/AssignedProperty.php @@ -11,19 +11,7 @@ */ final class AssignedProperty { - public Union $property_type; - - public string $id; - - public Union $assignment_type; - - public function __construct( - Union $property_type, - string $id, - Union $assignment_type, - ) { - $this->property_type = $property_type; - $this->id = $id; - $this->assignment_type = $assignment_type; + public function __construct(public Union $property_type, public string $id, public Union $assignment_type) + { } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/InstancePropertyAssignmentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/InstancePropertyAssignmentAnalyzer.php index 88a2bf6b511..c11731e2758 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/InstancePropertyAssignmentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/InstancePropertyAssignmentAnalyzer.php @@ -122,7 +122,7 @@ public static function analyze( $statements_analyzer, $context, ); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { // do nothing } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php index fa721397922..aea4fba535e 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php @@ -92,6 +92,8 @@ use function is_string; use function reset; use function spl_object_id; +use function str_contains; +use function str_starts_with; use function strpos; use function strtolower; @@ -400,7 +402,7 @@ public static function analyze( if (!$assign_var instanceof PhpParser\Node\Expr\PropertyFetch && !strpos($root_var_id ?? '', '->') && !$comment_type - && strpos($var_id ?? '', '$_') !== 0 + && !str_starts_with($var_id ?? '', '$_') ) { $origin_locations = []; @@ -962,7 +964,7 @@ public static function analyzeAssignmentRef( // Remove old reference parent node so previously referenced variable usage doesn't count as reference usage $old_type = $context->vars_in_scope[$lhs_var_id]; foreach ($old_type->parent_nodes as $old_parent_node_id => $_) { - if (strpos($old_parent_node_id, "$lhs_var_id-") === 0) { + if (str_starts_with($old_parent_node_id, "$lhs_var_id-")) { unset($old_type->parent_nodes[$old_parent_node_id]); } } @@ -975,12 +977,12 @@ public static function analyzeAssignmentRef( $context->hasVariable($lhs_var_id); $context->references_in_scope[$lhs_var_id] = $rhs_var_id; $context->referenced_counts[$rhs_var_id] = ($context->referenced_counts[$rhs_var_id] ?? 0) + 1; - if (strpos($rhs_var_id, '[') !== false) { + if (str_contains($rhs_var_id, '[')) { // Reference to array item, we always consider array items to be an external scope for references // TODO handle differently so it's detected as unused if the array is unused? $context->references_to_external_scope[$lhs_var_id] = true; } - if (strpos($rhs_var_id, '->') !== false) { + if (str_contains($rhs_var_id, '->')) { IssueBuffer::maybeAdd( new UnsupportedPropertyReferenceUsage( new CodeLocation($statements_analyzer->getSource(), $stmt), @@ -991,7 +993,7 @@ public static function analyzeAssignmentRef( // TODO handle differently so it's detected as unused if the object is unused? $context->references_to_external_scope[$lhs_var_id] = true; } - if (strpos($rhs_var_id, '::') !== false) { + if (str_contains($rhs_var_id, '::')) { IssueBuffer::maybeAdd( new UnsupportedPropertyReferenceUsage( new CodeLocation($statements_analyzer->getSource(), $stmt), @@ -1370,7 +1372,7 @@ private static function analyzeDestructuringAssignment( $already_in_scope = isset($context->vars_in_scope[$list_var_id]); - if (strpos($list_var_id, '-') === false && strpos($list_var_id, '[') === false) { + if (!str_contains($list_var_id, '-') && !str_contains($list_var_id, '[')) { $location = new CodeLocation($statements_analyzer, $var); if (!$statements_analyzer->hasVariable($list_var_id)) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php index 911827f2c4a..ec0967aee0a 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php @@ -188,20 +188,11 @@ public static function analyze( if ($context->if_body_context && !$context->inside_negation) { $if_body_context = $context->if_body_context; $context->vars_in_scope = $right_context->vars_in_scope; - $if_body_context->vars_in_scope = array_merge( - $if_body_context->vars_in_scope, - $context->vars_in_scope, - ); + $if_body_context->vars_in_scope = [...$if_body_context->vars_in_scope, ...$context->vars_in_scope]; - $if_body_context->cond_referenced_var_ids = array_merge( - $if_body_context->cond_referenced_var_ids, - $context->cond_referenced_var_ids, - ); + $if_body_context->cond_referenced_var_ids = [...$if_body_context->cond_referenced_var_ids, ...$context->cond_referenced_var_ids]; - $if_body_context->assigned_var_ids = array_merge( - $if_body_context->assigned_var_ids, - $context->assigned_var_ids, - ); + $if_body_context->assigned_var_ids = [...$if_body_context->assigned_var_ids, ...$context->assigned_var_ids]; $if_body_context->reconciled_expression_clauses = [ ...$if_body_context->reconciled_expression_clauses, @@ -212,10 +203,7 @@ public static function analyze( ), ]; - $if_body_context->vars_possibly_in_scope = array_merge( - $if_body_context->vars_possibly_in_scope, - $context->vars_possibly_in_scope, - ); + $if_body_context->vars_possibly_in_scope = [...$if_body_context->vars_possibly_in_scope, ...$context->vars_possibly_in_scope]; $if_body_context->updateChecks($context); } else { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php index 90e8f78b881..e95644d440d 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php @@ -4,6 +4,7 @@ namespace Psalm\Internal\Analyzer\Statements\Expression\BinaryOp; +use Decimal\Decimal; use PhpParser; use Psalm\CodeLocation; use Psalm\Codebase; @@ -48,7 +49,6 @@ use function array_diff_key; use function array_values; use function count; -use function get_class; use function is_int; use function is_numeric; use function max; @@ -321,7 +321,7 @@ private static function analyzeOperands( // get_class is fine here because both classes are final. if ($statements_source !== null && $config->strict_binary_operands - && get_class($left_type_part) !== get_class($right_type_part) + && $left_type_part::class !== $right_type_part::class ) { IssueBuffer::maybeAdd( new InvalidOperand( @@ -687,7 +687,7 @@ private static function analyzeOperands( && strtolower($non_decimal_type->value) === "decimal\\decimal" ) { $result_type = Type::combineUnionTypes( - new Union([new TNamedObject("Decimal\\Decimal")]), + new Union([new TNamedObject(Decimal::class)]), $result_type, ); } else { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ConcatAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ConcatAnalyzer.php index b3f7a03e5ed..bbf91777985 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ConcatAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ConcatAnalyzer.php @@ -425,7 +425,7 @@ private static function analyzeOperand( )) { try { $storage = $codebase->methods->getStorage($to_string_method_id); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { continue; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php index eaf715bfa37..886dadbf075 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php @@ -92,7 +92,7 @@ public static function analyze( if ($stmt->left instanceof PhpParser\Node\Expr\BinaryOp\BooleanOr) { $post_leaving_if_context = clone $context; } - } catch (ScopeAnalysisException $e) { + } catch (ScopeAnalysisException) { return false; } } else { @@ -132,10 +132,10 @@ public static function analyze( } $left_referenced_var_ids = $left_context->cond_referenced_var_ids; - $left_context->cond_referenced_var_ids = array_merge($pre_referenced_var_ids, $left_referenced_var_ids); + $left_context->cond_referenced_var_ids = [...$pre_referenced_var_ids, ...$left_referenced_var_ids]; $left_assigned_var_ids = array_diff_key($left_context->assigned_var_ids, $pre_assigned_var_ids); - $left_context->assigned_var_ids = array_merge($pre_assigned_var_ids, $left_context->assigned_var_ids); + $left_context->assigned_var_ids = [...$pre_assigned_var_ids, ...$left_context->assigned_var_ids]; $left_referenced_var_ids = array_diff_key($left_referenced_var_ids, $left_assigned_var_ids); } @@ -153,7 +153,7 @@ public static function analyze( try { $negated_left_clauses = Algebra::negateFormula($left_clauses); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { try { $negated_left_clauses = FormulaGenerator::getFormula( $left_cond_id, @@ -164,7 +164,7 @@ public static function analyze( $codebase, false, ); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { return false; } } @@ -354,15 +354,9 @@ public static function analyze( $context->updateChecks($right_context); } - $context->cond_referenced_var_ids = array_merge( - $right_context->cond_referenced_var_ids, - $context->cond_referenced_var_ids, - ); + $context->cond_referenced_var_ids = [...$right_context->cond_referenced_var_ids, ...$context->cond_referenced_var_ids]; - $context->assigned_var_ids = array_merge( - $context->assigned_var_ids, - $right_context->assigned_var_ids, - ); + $context->assigned_var_ids = [...$context->assigned_var_ids, ...$right_context->assigned_var_ids]; if ($context->if_body_context) { $if_body_context = $context->if_body_context; @@ -383,23 +377,14 @@ public static function analyze( } } - $if_body_context->cond_referenced_var_ids = array_merge( - $context->cond_referenced_var_ids, - $if_body_context->cond_referenced_var_ids, - ); + $if_body_context->cond_referenced_var_ids = [...$context->cond_referenced_var_ids, ...$if_body_context->cond_referenced_var_ids]; - $if_body_context->assigned_var_ids = array_merge( - $context->assigned_var_ids, - $if_body_context->assigned_var_ids, - ); + $if_body_context->assigned_var_ids = [...$context->assigned_var_ids, ...$if_body_context->assigned_var_ids]; $if_body_context->updateChecks($context); } - $context->vars_possibly_in_scope = array_merge( - $right_context->vars_possibly_in_scope, - $context->vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$right_context->vars_possibly_in_scope, ...$context->vars_possibly_in_scope]; return true; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php index b7c3ab3969c..9a782307f13 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php @@ -471,7 +471,7 @@ private static function checkForImpureEqualityComparison( '__tostring', ), ); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { continue; } @@ -505,7 +505,7 @@ private static function checkForImpureEqualityComparison( '__tostring', ), ); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { continue; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php index 060ed42d1a7..73b33b1859c 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php @@ -69,6 +69,8 @@ use function ord; use function preg_split; use function reset; +use function str_contains; +use function str_starts_with; use function strpos; use function strtolower; use function substr; @@ -683,7 +685,7 @@ public static function verifyType( && !$param_type->from_docblock && !$param_type->had_template && $method_id - && strpos($method_id->method_name, '__') !== 0 + && !str_starts_with($method_id->method_name, '__') ) { $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); @@ -1233,7 +1235,7 @@ private static function verifyExplicitParam( ); foreach ($function_ids as $function_id) { - if (strpos($function_id, '::') !== false) { + if (str_contains($function_id, '::')) { if ($function_id[0] === '$') { $function_id = substr($function_id, 1); } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php index 15eb539d662..122ca5387fa 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php @@ -60,7 +60,7 @@ use function max; use function min; use function reset; -use function strpos; +use function str_contains; use function strtolower; /** @@ -447,7 +447,7 @@ private static function handleClosureArg( $statements_analyzer->getFilePath(), $closure_id, ); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { return; } @@ -1115,7 +1115,7 @@ private static function handlePossiblyMatchingByRefParam( $by_ref_type, $by_ref_out_type ?: $by_ref_type, $context, - $method_id && (strpos($method_id, '::') !== false || !InternalCallMapHandler::inCallMap($method_id)), + $method_id && (str_contains($method_id, '::') || !InternalCallMapHandler::inCallMap($method_id)), $check_null_ref, ); } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php index f252f93bde6..e011b84fc82 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php @@ -43,7 +43,6 @@ use UnexpectedValueException; use function array_filter; -use function array_merge; use function array_pop; use function array_shift; use function array_unshift; @@ -51,7 +50,7 @@ use function count; use function explode; use function is_numeric; -use function strpos; +use function str_contains; use function strtolower; use function substr; @@ -460,11 +459,7 @@ public static function handleSplice( $length_min = (int) $length_literal->value; } } else { - $literals = array_merge( - $length_arg_type->getLiteralStrings(), - $length_arg_type->getLiteralInts(), - $length_arg_type->getLiteralFloats(), - ); + $literals = [...$length_arg_type->getLiteralStrings(), ...$length_arg_type->getLiteralInts(), ...$length_arg_type->getLiteralFloats()]; foreach ($literals as $literal) { if ($literal->isNumericType() && ($literal_val = (int) $literal->value) @@ -766,7 +761,7 @@ private static function checkClosureType( foreach ($function_ids as $function_id) { $function_id = strtolower($function_id); - if (strpos($function_id, '::') !== false) { + if (str_contains($function_id, '::')) { if ($function_id[0] === '$') { $function_id = substr($function_id, 1); } @@ -804,7 +799,7 @@ private static function checkClosureType( try { $method_storage = $codebase->methods->getStorage($function_id_part); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { // the method may not exist, but we're suppressing that issue continue; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php index 77a6d7d6118..f23cb61a17d 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php @@ -236,10 +236,7 @@ public static function analyze( $function_call_info->function_id, ); - $template_result->lower_bounds = array_merge( - $template_result->lower_bounds, - $already_inferred_lower_bounds, - ); + $template_result->lower_bounds = [...$template_result->lower_bounds, ...$already_inferred_lower_bounds]; if ($function_name instanceof PhpParser\Node\Name && $function_call_info->function_id) { $stmt_type = FunctionCallReturnTypeFetcher::fetch( @@ -567,7 +564,7 @@ private static function handleNamedFunction( $function_call_info->defined_constants = $function_storage->defined_constants; $function_call_info->global_variables = $function_storage->global_variables; } - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { $function_call_info->function_params = [ new FunctionLikeParameter('args', false, null, null, null, null, false, false, true), ]; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php index 2d35a9c8168..542491ec944 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php @@ -47,8 +47,9 @@ use function count; use function explode; use function in_array; +use function str_contains; +use function str_ends_with; use function strlen; -use function strpos; use function strtolower; use function substr; @@ -232,7 +233,7 @@ public static function fetch( ); } } - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // this can happen when the function was defined in the Config startup script $stmt_type = Type::getMixed(); } @@ -278,7 +279,7 @@ public static function fetch( $fake_call_factory = new BuilderFactory(); - if (strpos($proxy_call['fqn'], '::') !== false) { + if (str_contains($proxy_call['fqn'], '::')) { [$fqcn, $method] = explode('::', $proxy_call['fqn']); $fake_call = $fake_call_factory->staticCall($fqcn, $method, $fake_call_arguments); } else { @@ -634,7 +635,7 @@ private static function taintReturnType( if ($pattern[0] === '[' && $pattern[1] === '^' - && substr($pattern, -1) === ']' + && str_ends_with($pattern, ']') ) { $pattern = substr($pattern, 2, -1); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgHandler.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgHandler.php index ff627e40f54..9d36b1e251f 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgHandler.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgHandler.php @@ -21,7 +21,7 @@ use UnexpectedValueException; use function is_string; -use function strpos; +use function str_contains; use function strtolower; /** @@ -274,7 +274,7 @@ public static function getCallableArgInfo( $class_storage, ); } - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { return null; } @@ -316,7 +316,7 @@ private static function fromLiteralString( return new HighOrderFunctionArgInfo( HighOrderFunctionArgInfo::TYPE_STRING_CALLABLE, - strpos($literal->value, '::') !== false + str_contains($literal->value, '::') ? $codebase->methods->getStorage(MethodIdentifier::wrap($literal->value)) : $codebase->functions->getStorage($statements_analyzer, strtolower($literal->value)), ); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php index c7cb62a05a3..9f5dc9da433 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php @@ -12,8 +12,6 @@ use Psalm\Type\Atomic\TClosure; use Psalm\Type\Union; -use function array_merge; - /** * @internal */ @@ -24,31 +22,21 @@ final class HighOrderFunctionArgInfo public const TYPE_STRING_CALLABLE = 'string-callable'; public const TYPE_CALLABLE = 'callable'; - /** @psalm-var HighOrderFunctionArgInfo::TYPE_* */ - private string $type; - private FunctionLikeStorage $function_storage; - private ?ClassLikeStorage $class_storage; - /** * @psalm-param HighOrderFunctionArgInfo::TYPE_* $type */ public function __construct( - string $type, - FunctionLikeStorage $function_storage, - ClassLikeStorage $class_storage = null, + /** @psalm-var HighOrderFunctionArgInfo::TYPE_* */ + private readonly string $type, + private readonly FunctionLikeStorage $function_storage, + private readonly ?ClassLikeStorage $class_storage = null, ) { - $this->type = $type; - $this->function_storage = $function_storage; - $this->class_storage = $class_storage; } public function getTemplates(): TemplateResult { $templates = $this->class_storage - ? array_merge( - $this->function_storage->template_types ?? [], - $this->class_storage->template_types ?? [], - ) + ? [...$this->function_storage->template_types ?? [], ...$this->class_storage->template_types ?? []] : $this->function_storage->template_types ?? []; return new TemplateResult($templates, []); @@ -61,30 +49,24 @@ public function getType(): string public function getFunctionType(): Union { - switch ($this->type) { - case self::TYPE_FIRST_CLASS_CALLABLE: - return new Union([ - new TClosure( - 'Closure', - $this->function_storage->params, - $this->function_storage->return_type, - $this->function_storage->pure, - ), - ]); - - case self::TYPE_STRING_CALLABLE: - case self::TYPE_CLASS_CALLABLE: - return new Union([ - new TCallable( - 'callable', - $this->function_storage->params, - $this->function_storage->return_type, - $this->function_storage->pure, - ), - ]); - - default: - return $this->function_storage->return_type ?? Type::getMixed(); - } + return match ($this->type) { + self::TYPE_FIRST_CLASS_CALLABLE => new Union([ + new TClosure( + 'Closure', + $this->function_storage->params, + $this->function_storage->return_type, + $this->function_storage->pure, + ), + ]), + self::TYPE_STRING_CALLABLE, self::TYPE_CLASS_CALLABLE => new Union([ + new TCallable( + 'callable', + $this->function_storage->params, + $this->function_storage->return_type, + $this->function_storage->pure, + ), + ]), + default => $this->function_storage->return_type ?? Type::getMixed(), + }; } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicCallContext.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicCallContext.php index 131ca47c79e..419ab0ecbf6 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicCallContext.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicCallContext.php @@ -12,15 +12,8 @@ */ final class AtomicCallContext { - public MethodIdentifier $method_id; - - /** @var list */ - public array $args; - /** @param list $args */ - public function __construct(MethodIdentifier $method_id, array $args) + public function __construct(public MethodIdentifier $method_id, public array $args) { - $this->method_id = $method_id; - $this->args = $args; } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php index 6ca257415ee..4838c5e04d1 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php @@ -51,7 +51,6 @@ use function array_shift; use function array_values; use function count; -use function get_class; use function reset; use function strtolower; @@ -619,7 +618,7 @@ private static function handleInvalidClass( bool $is_intersection, AtomicMethodCallAnalysisResult $result, ): void { - switch (get_class($lhs_type_part)) { + switch ($lhs_type_part::class) { case TNull::class: case TFalse::class: // handled above diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/ExistingAtomicMethodCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/ExistingAtomicMethodCallAnalyzer.php index d0de3e5995a..d5a2ef0b25f 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/ExistingAtomicMethodCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/ExistingAtomicMethodCallAnalyzer.php @@ -51,7 +51,7 @@ use function explode; use function in_array; use function is_string; -use function strpos; +use function str_starts_with; use function strtolower; /** @@ -205,7 +205,7 @@ public static function analyze( try { $method_storage = $codebase->methods->getStorage($declaring_method_id ?? $method_id); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { $method_storage = null; } @@ -446,7 +446,7 @@ public static function analyze( $possibilities = array_filter( $possibilities, static fn(Possibilities $assertion): bool => !(is_string($assertion->var_id) - && strpos($assertion->var_id, '$this->') === 0 + && str_starts_with($assertion->var_id, '$this->') ) ); } @@ -469,7 +469,7 @@ public static function analyze( $possibilities = array_filter( $possibilities, static fn(Possibilities $assertion): bool => !(is_string($assertion->var_id) - && strpos($assertion->var_id, '$this->') === 0 + && str_starts_with($assertion->var_id, '$this->') ) ); } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NamedFunctionCallHandler.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NamedFunctionCallHandler.php index a4f0c47d864..ef3e7b335cc 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NamedFunctionCallHandler.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NamedFunctionCallHandler.php @@ -52,6 +52,7 @@ use function extension_loaded; use function in_array; use function is_string; +use function str_starts_with; use function strpos; use function strtolower; @@ -392,7 +393,7 @@ public static function handle( if ($first_arg && $function_id - && strpos($function_id, 'is_') === 0 + && str_starts_with($function_id, 'is_') && $function_id !== 'is_a' && !$context->inside_negation ) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php index b32b19373cb..d8f61a14b2b 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php @@ -246,7 +246,7 @@ public static function analyze( new Union([$result_atomic_type]), ); - if (strtolower($fq_class_name) !== 'stdclass' && + if (strtolower((string) $fq_class_name) !== 'stdclass' && $codebase->classlikes->classExists($fq_class_name) ) { self::analyzeNamedConstructor( diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php index cfc1fedaacc..45806955441 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php @@ -964,7 +964,7 @@ private static function checkPseudoMethod( new CodeLocation($statements_analyzer, $stmt), $context, ); - } catch (Exception $e) { + } catch (Exception) { // do nothing } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php index c87fa0f8462..96b2f8b2a8c 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php @@ -44,6 +44,7 @@ use function explode; use function in_array; use function is_string; +use function str_starts_with; use function strlen; use function strpos; use function strtolower; @@ -113,13 +114,13 @@ public static function analyze( $local_vars_possibly_in_scope = []; foreach ($context->vars_in_scope as $var => $_) { - if (strpos($var, '$this->') !== 0 && $var !== '$this') { + if (!str_starts_with($var, '$this->') && $var !== '$this') { $local_vars_in_scope[$var] = $context->vars_in_scope[$var]; } } foreach ($context->vars_possibly_in_scope as $var => $_) { - if (strpos($var, '$this->') !== 0 && $var !== '$this') { + if (!str_starts_with($var, '$this->') && $var !== '$this') { $local_vars_possibly_in_scope[$var] = $context->vars_possibly_in_scope[$var]; } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index 666ccbc7d8a..25b9f104cb3 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -68,8 +68,9 @@ use function preg_match; use function preg_replace; use function spl_object_id; +use function str_contains; use function str_replace; -use function strpos; +use function str_starts_with; use function strtolower; /** @@ -227,7 +228,7 @@ public static function collectSpecialInformation( $local_vars_in_scope = []; foreach ($context->vars_in_scope as $var_id => $type) { - if (strpos($var_id, '$this->') === 0) { + if (str_starts_with($var_id, '$this->')) { if ($type->initialized) { $local_vars_in_scope[$var_id] = $context->vars_in_scope[$var_id]; @@ -675,16 +676,16 @@ public static function applyAssertionsToContext( } } elseif ($var_possibilities->var_id === '$this' && $thisName !== null) { $assertion_var_id = $thisName; - } elseif (strpos($var_possibilities->var_id, '$this->') === 0 && $thisName !== null) { + } elseif (str_starts_with($var_possibilities->var_id, '$this->') && $thisName !== null) { $assertion_var_id = $thisName . str_replace('$this->', '->', $var_possibilities->var_id); - } elseif (strpos($var_possibilities->var_id, 'self::') === 0 && $context->self) { + } elseif (str_starts_with($var_possibilities->var_id, 'self::') && $context->self) { $assertion_var_id = $context->self . str_replace('self::', '::', $var_possibilities->var_id); - } elseif (strpos($var_possibilities->var_id, '::$') !== false) { + } elseif (str_contains($var_possibilities->var_id, '::$')) { // allow assertions to bring external static props into scope $assertion_var_id = $var_possibilities->var_id; } elseif (isset($context->vars_in_scope[$var_possibilities->var_id])) { $assertion_var_id = $var_possibilities->var_id; - } elseif (strpos($var_possibilities->var_id, '->') !== false) { + } elseif (str_contains($var_possibilities->var_id, '->')) { $exploded = explode('->', $var_possibilities->var_id); if (count($exploded) < 2) { @@ -881,7 +882,7 @@ public static function applyAssertionsToContext( $simplified_clauses, ); - $type_assertions = array_merge($type_assertions, $assert_type_assertions); + $type_assertions = [...$type_assertions, ...$assert_type_assertions]; } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php index 3856f18a1ad..65f24af9f03 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php @@ -53,7 +53,6 @@ use function array_merge; use function array_pop; use function array_values; -use function get_class; use function strtolower; /** @@ -299,7 +298,7 @@ public static function analyze( IssueBuffer::maybeAdd( new UnrecognizedExpression( - 'Psalm does not understand the cast ' . get_class($stmt), + 'Psalm does not understand the cast ' . $stmt::class, new CodeLocation($statements_analyzer->getSource(), $stmt), ), $statements_analyzer->getSuppressedIssues(), @@ -394,7 +393,7 @@ public static function castIntAttempt( $intersection_types = [$atomic_type]; if ($atomic_type->extra_types) { - $intersection_types = array_merge($intersection_types, $atomic_type->extra_types); + $intersection_types = [...$intersection_types, ...$atomic_type->extra_types]; } foreach ($intersection_types as $intersection_type) { @@ -476,7 +475,7 @@ public static function castIntAttempt( // todo: emit error here } - $valid_types = array_merge($valid_ints, $castable_types); + $valid_types = [...$valid_ints, ...$castable_types]; if (!$valid_types) { $int_type = Type::getInt(); @@ -579,7 +578,7 @@ public static function castFloatAttempt( $intersection_types = [$atomic_type]; if ($atomic_type->extra_types) { - $intersection_types = array_merge($intersection_types, $atomic_type->extra_types); + $intersection_types = [...$intersection_types, ...$atomic_type->extra_types]; } foreach ($intersection_types as $intersection_type) { @@ -661,7 +660,7 @@ public static function castFloatAttempt( // todo: emit error here } - $valid_types = array_merge($valid_floats, $castable_types); + $valid_types = [...$valid_floats, ...$castable_types]; if (!$valid_types) { $float_type = Type::getFloat(); @@ -804,10 +803,7 @@ public static function castStringAttempt( $parent_nodes = array_merge($return_type->parent_nodes, $parent_nodes); } - $castable_types = array_merge( - $castable_types, - array_values($return_type->getAtomicTypes()), - ); + $castable_types = [...$castable_types, ...array_values($return_type->getAtomicTypes())]; continue 2; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php index 15723ccb0e5..793993aa6c3 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php @@ -263,9 +263,9 @@ public static function analyzeFetch( [], $stmt->class->getFirst() === "static", ); - } catch (InvalidArgumentException $_) { + } catch (InvalidArgumentException) { return true; - } catch (CircularReferenceException $e) { + } catch (CircularReferenceException) { IssueBuffer::maybeAdd( new CircularReference( 'Constant ' . $const_id . ' contains a circular reference', @@ -563,9 +563,9 @@ public static function analyzeFetch( $class_visibility, $statements_analyzer, ); - } catch (InvalidArgumentException $_) { + } catch (InvalidArgumentException) { return true; - } catch (CircularReferenceException $e) { + } catch (CircularReferenceException) { IssueBuffer::maybeAdd( new CircularReference( 'Constant ' . $const_id . ' contains a circular reference', diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php index 44d61115739..9d55139838d 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php @@ -269,7 +269,7 @@ public static function analyze( try { $new_class_storage = $codebase->classlike_storage_provider->get($mixin->value); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { $new_class_storage = null; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php index b690b0af42a..b7766aa2617 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php @@ -575,11 +575,7 @@ public static function getGlobalType(string $var_id, int $codebase_analysis_php_ $var_id = '$_FILES full path'; } - if (isset(self::$globalCache[$var_id])) { - return self::$globalCache[$var_id]; - } - - return Type::getMixed(); + return self::$globalCache[$var_id] ?? Type::getMixed(); } /** @@ -640,7 +636,7 @@ private static function getGlobalTypeInner(string $var_id, bool $files_full_path return new Union([$type]); } - if (in_array($var_id, array('$_GET', '$_POST', '$_REQUEST'), true)) { + if (in_array($var_id, ['$_GET', '$_POST', '$_REQUEST'], true)) { $array_key = new Union([new TNonEmptyString(), new TInt()]); $array = new TNonEmptyArray( [ diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php index 83123189023..84de2e653ad 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php @@ -209,7 +209,7 @@ public static function analyze( $context, $global_context, ); - } catch (UnpreparedAnalysisException $e) { + } catch (UnpreparedAnalysisException) { if ($config->skip_checks_on_unresolvable_includes) { $context->check_classes = false; $context->check_variables = false; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php index f12b0ebc553..0f7ef50530e 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php @@ -354,7 +354,7 @@ public static function infer( } return null; - } catch (InvalidArgumentException | CircularReferenceException $e) { + } catch (InvalidArgumentException | CircularReferenceException) { return null; } } @@ -482,11 +482,7 @@ public static function infer( foreach ($array_type->getAtomicTypes() as $array_atomic_type) { if ($array_atomic_type instanceof TKeyedArray) { - if (isset($array_atomic_type->properties[$dim_value])) { - return $array_atomic_type->properties[$dim_value]; - } - - return null; + return $array_atomic_type->properties[$dim_value] ?? null; } } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php index 814568e4fdc..671b151659b 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php @@ -29,7 +29,6 @@ use function array_intersect_key; use function array_keys; use function array_map; -use function array_merge; use function array_values; use function count; use function in_array; @@ -66,7 +65,7 @@ public static function analyze( $cond_referenced_var_ids = $if_conditional_scope->cond_referenced_var_ids; $assigned_in_conditional_var_ids = $if_conditional_scope->assigned_in_conditional_var_ids; - } catch (ScopeAnalysisException $e) { + } catch (ScopeAnalysisException) { return false; } @@ -156,7 +155,7 @@ static function (Clause $c) use ($mixed_var_ids, $cond_object_id): Clause { try { $if_scope->negated_clauses = Algebra::negateFormula($if_clauses); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { try { $if_scope->negated_clauses = FormulaGenerator::getFormula( $cond_object_id, @@ -167,7 +166,7 @@ static function (Clause $c) use ($mixed_var_ids, $cond_object_id): Clause { $codebase, false, ); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $if_scope->negated_clauses = []; } } @@ -211,10 +210,7 @@ static function (Clause $c) use ($mixed_var_ids, $cond_object_id): Clause { return false; } - $context->cond_referenced_var_ids = array_merge( - $context->cond_referenced_var_ids, - $if_context->cond_referenced_var_ids, - ); + $context->cond_referenced_var_ids = [...$context->cond_referenced_var_ids, ...$if_context->cond_referenced_var_ids]; } $t_else_context->clauses = Algebra::simplifyCNF( @@ -290,16 +286,9 @@ static function (Clause $c) use ($mixed_var_ids, $cond_object_id): Clause { } } - $context->vars_possibly_in_scope = array_merge( - $context->vars_possibly_in_scope, - $if_context->vars_possibly_in_scope, - $t_else_context->vars_possibly_in_scope, - ); + $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$if_context->vars_possibly_in_scope, ...$t_else_context->vars_possibly_in_scope]; - $context->cond_referenced_var_ids = array_merge( - $context->cond_referenced_var_ids, - $t_else_context->cond_referenced_var_ids, - ); + $context->cond_referenced_var_ids = [...$context->cond_referenced_var_ids, ...$t_else_context->cond_referenced_var_ids]; $lhs_type = null; $stmt_cond_type = $statements_analyzer->node_data->getType($stmt->cond); diff --git a/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php index 870201bc289..3fdf106e218 100644 --- a/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php @@ -60,7 +60,6 @@ use Psalm\Type; use Psalm\Type\TaintKind; -use function get_class; use function in_array; use function strtolower; @@ -502,7 +501,7 @@ private static function handleExpression( IssueBuffer::maybeAdd( new UnrecognizedExpression( - 'Psalm does not understand ' . get_class($stmt) . ' for PHP ' . + 'Psalm does not understand ' . $stmt::class . ' for PHP ' . $codebase->getMajorAnalysisPhpVersion() . '.' . $codebase->getMinorAnalysisPhpVersion(), new CodeLocation($statements_analyzer->getSource(), $stmt), ), diff --git a/src/Psalm/Internal/Analyzer/Statements/StaticAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/StaticAnalyzer.php index 02b411bc3d4..1cdd6a8b8a2 100644 --- a/src/Psalm/Internal/Analyzer/Statements/StaticAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/StaticAnalyzer.php @@ -89,7 +89,7 @@ public static function analyze( } if ($context->check_variables) { - $context->vars_in_scope[$var_id] = $comment_type ? $comment_type : Type::getMixed(); + $context->vars_in_scope[$var_id] = $comment_type ?: Type::getMixed(); $context->vars_possibly_in_scope[$var_id] = true; $context->assigned_var_ids[$var_id] = (int) $stmt->getAttribute('startFilePos'); $statements_analyzer->byref_uses[$var_id] = true; diff --git a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php index 183255e19ee..be5d5e48762 100644 --- a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php @@ -76,14 +76,13 @@ use function count; use function explode; use function fwrite; -use function get_class; use function in_array; use function is_string; use function preg_split; use function reset; use function round; +use function str_starts_with; use function strlen; -use function strpos; use function strrpos; use function strtolower; use function substr; @@ -97,8 +96,6 @@ */ final class StatementsAnalyzer extends SourceAnalyzer { - protected SourceAnalyzer $source; - protected FileAnalyzer $file_analyzer; protected Codebase $codebase; @@ -139,8 +136,6 @@ final class StatementsAnalyzer extends SourceAnalyzer private ?string $fake_this_class = null; - public NodeDataProvider $node_data; - public ?DataFlowGraph $data_flow_graph = null; /** @@ -153,12 +148,10 @@ final class StatementsAnalyzer extends SourceAnalyzer */ public array $foreach_var_locations = []; - public function __construct(SourceAnalyzer $source, NodeDataProvider $node_data) + public function __construct(protected SourceAnalyzer $source, public NodeDataProvider $node_data) { - $this->source = $source; $this->file_analyzer = $source->getFileAnalyzer(); $this->codebase = $source->getCodebase(); - $this->node_data = $node_data; if ($this->codebase->taint_flow_graph) { $this->data_flow_graph = new TaintFlowGraph(); @@ -271,7 +264,7 @@ private function hoistFunctions(array $stmts, Context $context): void try { $function_analyzer = new FunctionAnalyzer($stmt, $this->source); $this->function_analyzers[$fq_function_name] = $function_analyzer; - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { // do nothing } } @@ -587,7 +580,7 @@ private static function analyzeStatement( ); $class_analyzer->analyze(null, $global_context); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // disregard this exception, we'll likely see it elsewhere in the form // of an issue } @@ -606,7 +599,7 @@ private static function analyzeStatement( } else { if (IssueBuffer::accepts( new UnrecognizedStatement( - 'Psalm does not understand ' . get_class($stmt), + 'Psalm does not understand ' . $stmt::class, new CodeLocation($statements_analyzer->source, $stmt), ), $statements_analyzer->getSuppressedIssues(), @@ -863,7 +856,7 @@ public function checkUnreferencedVars(array $stmts, Context $context): void } foreach ($this->unused_var_locations as [$var_id, $original_location]) { - if (strpos($var_id, '$_') === 0) { + if (str_starts_with($var_id, '$_')) { continue; } @@ -1094,7 +1087,7 @@ public function getUncaughtThrows(Context $context): array $is_expected = true; break; } - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { $is_expected = true; break; } diff --git a/src/Psalm/Internal/Analyzer/TraitAnalyzer.php b/src/Psalm/Internal/Analyzer/TraitAnalyzer.php index 6f8d4b86c3a..10de0e5eff5 100644 --- a/src/Psalm/Internal/Analyzer/TraitAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/TraitAnalyzer.php @@ -16,13 +16,11 @@ */ final class TraitAnalyzer extends ClassLikeAnalyzer { - private Aliases $aliases; - public function __construct( Trait_ $class, SourceAnalyzer $source, string $fq_class_name, - Aliases $aliases, + private Aliases $aliases, ) { $this->source = $source; $this->file_analyzer = $source->getFileAnalyzer(); @@ -31,7 +29,6 @@ public function __construct( $this->fq_class_name = $fq_class_name; $codebase = $source->getCodebase(); $this->storage = $codebase->classlike_storage_provider->get($fq_class_name); - $this->aliases = $aliases; } /** @psalm-mutation-free */ diff --git a/src/Psalm/Internal/Cache.php b/src/Psalm/Internal/Cache.php index 27a6a84c260..8467f1d066d 100644 --- a/src/Psalm/Internal/Cache.php +++ b/src/Psalm/Internal/Cache.php @@ -27,13 +27,10 @@ */ final class Cache { - private Config $config; - public bool $use_igbinary; - public function __construct(Config $config) + public function __construct(private readonly Config $config) { - $this->config = $config; $this->use_igbinary = $config->use_igbinary; } diff --git a/src/Psalm/Internal/Clause.php b/src/Psalm/Internal/Clause.php index 1482bbe736b..1e9c7dfbd84 100644 --- a/src/Psalm/Internal/Clause.php +++ b/src/Psalm/Internal/Clause.php @@ -11,6 +11,7 @@ use Psalm\Type\Atomic\TLiteralFloat; use Psalm\Type\Atomic\TLiteralInt; use Psalm\Type\Atomic\TLiteralString; +use Stringable; use function array_diff; use function array_keys; @@ -29,12 +30,10 @@ * @internal * @psalm-immutable */ -final class Clause +final class Clause implements Stringable { use ImmutableNonCloneableTrait; - public int $creating_conditional_id; - public int $creating_object_id; /** @@ -74,11 +73,6 @@ final class Clause public bool $reconcilable; - public bool $generated = false; - - /** @var array */ - public array $redefined_vars = []; - public string $hash; /** @@ -87,12 +81,12 @@ final class Clause */ public function __construct( array $possibilities, - int $creating_conditional_id, + public int $creating_conditional_id, int $creating_object_id, bool $wedge = false, bool $reconcilable = true, - bool $generated = false, - array $redefined_vars = [], + public bool $generated = false, + public array $redefined_vars = [], ) { if ($wedge || !$reconcilable) { $this->hash = ($wedge ? 'w' : '') . $creating_object_id; @@ -116,9 +110,6 @@ public function __construct( $this->possibilities = $possibilities; $this->wedge = $wedge; $this->reconcilable = $reconcilable; - $this->generated = $generated; - $this->redefined_vars = $redefined_vars; - $this->creating_conditional_id = $creating_conditional_id; $this->creating_object_id = $creating_object_id; } diff --git a/src/Psalm/Internal/Cli/LanguageServer.php b/src/Psalm/Internal/Cli/LanguageServer.php index 837e23c82b9..997ceffdc7e 100644 --- a/src/Psalm/Internal/Cli/LanguageServer.php +++ b/src/Psalm/Internal/Cli/LanguageServer.php @@ -35,8 +35,9 @@ use function preg_replace; use function realpath; use function setlocale; +use function str_contains; +use function str_starts_with; use function strlen; -use function strpos; use function strtolower; use function substr; @@ -111,7 +112,7 @@ public static function run(array $argv): void array_map( static function (string $arg) use ($valid_long_options): void { - if (strpos($arg, '--') === 0 && $arg !== '--') { + if (str_starts_with($arg, '--') && $arg !== '--') { $arg_name = (string) preg_replace('/=.*$/', '', substr($arg, 2), 1); if (!in_array($arg_name, $valid_long_options, true) @@ -437,7 +438,7 @@ private static function createPathMapper(array $options, string $server_start_di } if (is_string($map_folder)) { - if (strpos($map_folder, ':') === false) { + if (!str_contains($map_folder, ':')) { fwrite( STDERR, 'invalid format for --map-folder option' . PHP_EOL, diff --git a/src/Psalm/Internal/Cli/Psalm.php b/src/Psalm/Internal/Cli/Psalm.php index 5a2df4e477f..88a8fa895ac 100644 --- a/src/Psalm/Internal/Cli/Psalm.php +++ b/src/Psalm/Internal/Cli/Psalm.php @@ -71,8 +71,8 @@ use function realpath; use function setlocale; use function str_repeat; +use function str_starts_with; use function strlen; -use function strpos; use function substr; use function version_compare; @@ -422,7 +422,7 @@ private static function initOutputFormat(array $options): string private static function findDefaultOutputFormat(): string { $emulator = getenv('TERMINAL_EMULATOR'); - if (is_string($emulator) && substr($emulator, 0, 9) === 'JetBrains') { + if (is_string($emulator) && str_starts_with($emulator, 'JetBrains')) { return Report::TYPE_PHP_STORM; } @@ -454,7 +454,7 @@ private static function validateCliArguments(array $args): void { array_map( static function (string $arg): void { - if (strpos($arg, '--') === 0 && $arg !== '--') { + if (str_starts_with($arg, '--') && $arg !== '--') { $arg_name = (string) preg_replace('/=.*$/', '', substr($arg, 2), 1); if (!in_array($arg_name, self::LONG_OPTIONS) @@ -468,7 +468,7 @@ static function (string $arg): void { ); exit(1); } - } elseif (strpos($arg, '-') === 0 && $arg !== '-' && $arg !== '--') { + } elseif (str_starts_with($arg, '-') && $arg !== '-' && $arg !== '--') { $arg_name = (string) preg_replace('/=.*$/', '', substr($arg, 1)); if (!in_array($arg_name, self::SHORT_OPTIONS) @@ -505,9 +505,9 @@ private static function generateConfig(string $current_dir, array &$args): void && $arg !== '--debug' && $arg !== '--debug-by-line' && $arg !== '--debug-emitted-issues' - && strpos($arg, '--disable-extension=') !== 0 - && strpos($arg, '--root=') !== 0 - && strpos($arg, '--r=') !== 0 + && !str_starts_with($arg, '--disable-extension=') + && !str_starts_with($arg, '--root=') + && !str_starts_with($arg, '--r=') )); $init_level = null; @@ -656,7 +656,7 @@ private static function generateBaseline( new FileProvider, $options['set-baseline'], ); - } catch (ConfigException $e) { + } catch (ConfigException) { $issue_baseline = []; } diff --git a/src/Psalm/Internal/Cli/Psalter.php b/src/Psalm/Internal/Cli/Psalter.php index 242a27a967b..9e44e0a069f 100644 --- a/src/Psalm/Internal/Cli/Psalter.php +++ b/src/Psalm/Internal/Cli/Psalter.php @@ -56,7 +56,8 @@ use function preg_replace; use function preg_split; use function realpath; -use function strpos; +use function str_contains; +use function str_starts_with; use function strtolower; use function substr; use function trim; @@ -385,7 +386,7 @@ public static function run(array $argv): void foreach ($keyed_issues as $issue_name => $_) { // MissingParamType requires the scanning of all files to inform possible params - if (strpos($issue_name, 'Unused') !== false + if (str_contains($issue_name, 'Unused') || $issue_name === 'MissingParamType' || $issue_name === 'UnnecessaryVarAnnotation' || $issue_name === 'all' @@ -453,7 +454,7 @@ private static function validateCliArguments(array $args): void { array_map( static function (string $arg): void { - if (strpos($arg, '--') === 0 && $arg !== '--') { + if (str_starts_with($arg, '--') && $arg !== '--') { $arg_name = (string) preg_replace('/=.*$/', '', substr($arg, 2), 1); if ($arg_name === 'alter') { @@ -534,7 +535,7 @@ static function (string $line): bool { // currently we don’t match wildcard files or files that could appear anywhere // in the repo - return $line && $line[0] === '/' && strpos($line, '*') === false; + return $line && $line[0] === '/' && !str_contains($line, '*'); }, ), ); diff --git a/src/Psalm/Internal/Cli/Refactor.php b/src/Psalm/Internal/Cli/Refactor.php index b00848ddcb6..fecbb416057 100644 --- a/src/Psalm/Internal/Cli/Refactor.php +++ b/src/Psalm/Internal/Cli/Refactor.php @@ -46,6 +46,7 @@ use function preg_replace; use function preg_split; use function realpath; +use function str_starts_with; use function strpos; use function substr; @@ -93,7 +94,7 @@ public static function run(array $argv): void array_map( static function (string $arg) use ($valid_long_options): void { - if (strpos($arg, '--') === 0 && $arg !== '--') { + if (str_starts_with($arg, '--') && $arg !== '--') { $arg_name = (string) preg_replace('/=.*$/', '', substr($arg, 2), 1); if ($arg_name === 'refactor') { diff --git a/src/Psalm/Internal/CliUtils.php b/src/Psalm/Internal/CliUtils.php index 78d964f0b94..dc455ae9942 100644 --- a/src/Psalm/Internal/CliUtils.php +++ b/src/Psalm/Internal/CliUtils.php @@ -41,6 +41,7 @@ use function preg_replace; use function preg_split; use function realpath; +use function str_starts_with; use function stream_get_meta_data; use function stream_set_blocking; use function strlen; @@ -285,7 +286,7 @@ public static function getPathsToCheck(string|array|false|null $f_paths): ?array continue; } - if (strpos($input_path, '--') === 0 && strlen($input_path) > 2) { + if (str_starts_with($input_path, '--') && strlen($input_path) > 2) { if (substr($input_path, 2) === 'config') { ++$i; } diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php index e7eb49e1c15..3a13427bf3b 100644 --- a/src/Psalm/Internal/Codebase/Analyzer.php +++ b/src/Psalm/Internal/Codebase/Analyzer.php @@ -41,6 +41,8 @@ use function number_format; use function pathinfo; use function preg_replace; +use function str_ends_with; +use function str_starts_with; use function strlen; use function strpos; use function strtolower; @@ -99,14 +101,6 @@ */ final class Analyzer { - private Config $config; - - private FileProvider $file_provider; - - private FileStorageProvider $file_storage_provider; - - private Progress $progress; - /** * Used to store counts of mixed vs non-mixed variables * @@ -187,16 +181,8 @@ final class Analyzer */ public array $mutable_classes = []; - public function __construct( - Config $config, - FileProvider $file_provider, - FileStorageProvider $file_storage_provider, - Progress $progress, - ) { - $this->config = $config; - $this->file_provider = $file_provider; - $this->file_storage_provider = $file_storage_provider; - $this->progress = $progress; + public function __construct(private readonly Config $config, private readonly FileProvider $file_provider, private readonly FileStorageProvider $file_storage_provider, private readonly Progress $progress) + { } /** @@ -268,7 +254,7 @@ public function analyzeFiles( $this->files_to_analyze = array_filter( $this->files_to_analyze, - [$this->file_provider, 'fileExists'], + $this->file_provider->fileExists(...), ); $this->doAnalysis($project_analyzer, $pool_size); @@ -331,9 +317,9 @@ private function doAnalysis(ProjectAnalyzer $project_analyzer, int $pool_size): $codebase = $project_analyzer->getCodebase(); - $analysis_worker = Closure::fromCallable([$this, 'analysisWorker']); + $analysis_worker = Closure::fromCallable($this->analysisWorker(...)); - $task_done_closure = Closure::fromCallable([$this, 'taskDoneClosure']); + $task_done_closure = Closure::fromCallable($this->taskDoneClosure(...)); if ($pool_size > 1 && count($this->files_to_analyze) > $pool_size) { $shuffle_count = $pool_size + 1; @@ -395,7 +381,7 @@ static function (): void { $file_reference_provider->setMethodParamUses([]); }, $analysis_worker, - Closure::fromCallable([$this, 'getWorkerData']), + Closure::fromCallable($this->getWorkerData(...)), $task_done_closure, ); @@ -602,7 +588,7 @@ public function loadCachedResults(ProjectAnalyzer $project_analyzer): void [$base_class, $trait] = explode('&', $changed_member); foreach ($all_referencing_methods as $member_id => $_) { - if (strpos($member_id, $base_class . '::') !== 0) { + if (!str_starts_with($member_id, $base_class . '::')) { continue; } @@ -624,7 +610,7 @@ public function loadCachedResults(ProjectAnalyzer $project_analyzer): void // also check for things that might invalidate constructor property initialisation if (isset($all_referencing_methods[$unchanged_signature_member_id])) { foreach ($all_referencing_methods[$unchanged_signature_member_id] as $referencing_method_id => $_) { - if (substr($referencing_method_id, -13) === '::__construct') { + if (str_ends_with($referencing_method_id, '::__construct')) { $referencing_base_classlike = explode('::', $referencing_method_id)[0]; $unchanged_signature_classlike = explode('::', $unchanged_signature_member_id)[0]; @@ -635,7 +621,7 @@ public function loadCachedResults(ProjectAnalyzer $project_analyzer): void $referencing_storage = $codebase->classlike_storage_provider->get( $referencing_base_classlike, ); - } catch (InvalidArgumentException $_) { + } catch (InvalidArgumentException) { // Workaround for #3671 $newly_invalidated_methods[$referencing_method_id] = true; $referencing_storage = null; diff --git a/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php b/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php index 397633c5e19..40b1cdb6688 100644 --- a/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php +++ b/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php @@ -10,7 +10,6 @@ use Psalm\Storage\Possibilities; use function array_filter; -use function array_merge; use function array_values; use function strtolower; @@ -19,12 +18,8 @@ */ final class AssertionsFromInheritanceResolver { - private Codebase $codebase; - - public function __construct( - Codebase $codebase, - ) { - $this->codebase = $codebase; + public function __construct(private readonly Codebase $codebase) + { } /** @@ -37,10 +32,7 @@ public function resolve( $method_name_lc = strtolower($method_storage->cased_name ?? ''); $assertions = $method_storage->assertions; - $inherited_classes_and_interfaces = array_values(array_filter(array_merge( - $called_class->parent_classes, - $called_class->class_implements, - ), fn(string $classOrInterface) => $this->codebase->classOrInterfaceOrEnumExists($classOrInterface))); + $inherited_classes_and_interfaces = array_values(array_filter([...$called_class->parent_classes, ...$called_class->class_implements], fn(string $classOrInterface) => $this->codebase->classOrInterfaceOrEnumExists($classOrInterface))); foreach ($inherited_classes_and_interfaces as $potential_assertion_providing_class) { $potential_assertion_providing_classlike_storage = $this->codebase->classlike_storage_provider->get( diff --git a/src/Psalm/Internal/Codebase/ClassConstantByWildcardResolver.php b/src/Psalm/Internal/Codebase/ClassConstantByWildcardResolver.php index 0e6ef6f8a33..e7253d2f78e 100644 --- a/src/Psalm/Internal/Codebase/ClassConstantByWildcardResolver.php +++ b/src/Psalm/Internal/Codebase/ClassConstantByWildcardResolver.php @@ -15,13 +15,11 @@ */ final class ClassConstantByWildcardResolver { - private StorageByPatternResolver $resolver; - private Codebase $codebase; + private readonly StorageByPatternResolver $resolver; - public function __construct(Codebase $codebase) + public function __construct(private readonly Codebase $codebase) { $this->resolver = new StorageByPatternResolver(); - $this->codebase = $codebase; } /** diff --git a/src/Psalm/Internal/Codebase/ClassLikes.php b/src/Psalm/Internal/Codebase/ClassLikes.php index e7af2f4a19b..b829e026fac 100644 --- a/src/Psalm/Internal/Codebase/ClassLikes.php +++ b/src/Psalm/Internal/Codebase/ClassLikes.php @@ -75,10 +75,6 @@ */ final class ClassLikes { - private ClassLikeStorageProvider $classlike_storage_provider; - - public FileReferenceProvider $file_reference_provider; - /** * @var array */ @@ -143,25 +139,13 @@ final class ClassLikes public bool $collect_locations = false; - private StatementsProvider $statements_provider; - - private Config $config; - - private Scanner $scanner; - public function __construct( - Config $config, - ClassLikeStorageProvider $storage_provider, - FileReferenceProvider $file_reference_provider, - StatementsProvider $statements_provider, - Scanner $scanner, + private readonly Config $config, + private readonly ClassLikeStorageProvider $classlike_storage_provider, + public FileReferenceProvider $file_reference_provider, + private readonly StatementsProvider $statements_provider, + private readonly Scanner $scanner, ) { - $this->config = $config; - $this->classlike_storage_provider = $storage_provider; - $this->file_reference_provider = $file_reference_provider; - $this->statements_provider = $statements_provider; - $this->scanner = $scanner; - $this->collectPredefinedClassLikes(); } @@ -848,7 +832,7 @@ public function consolidateAnalyzedData(Methods $methods, ?Progress $progress, b foreach ($this->existing_classlikes_lc as $fq_class_name_lc => $_) { try { $classlike_storage = $this->classlike_storage_provider->get($fq_class_name_lc); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -955,7 +939,7 @@ public function moveMethods(Methods $methods, ?Progress $progress = null): void $source_method_storage = $methods->getStorage( new MethodIdentifier(...$source_parts), ); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -963,7 +947,7 @@ public function moveMethods(Methods $methods, ?Progress $progress = null): void try { $classlike_storage = $this->classlike_storage_provider->get($destination_fq_class_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -1032,7 +1016,7 @@ public function moveProperties(Properties $properties, ?Progress $progress = nul foreach ($codebase->properties_to_move as $source => $destination) { try { $source_property_storage = $properties->getStorage($source); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -1692,7 +1676,7 @@ private function checkMethodReferences(ClassLikeStorage $classlike_storage, Meth try { $declaring_classlike_storage = $this->classlike_storage_provider->get($declaring_fq_classlike_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -1792,7 +1776,7 @@ private function checkMethodReferences(ClassLikeStorage $classlike_storage, Meth foreach ($classlike_storage->class_implements as $fq_interface_name_lc => $_) { try { $interface_storage = $this->classlike_storage_provider->get($fq_interface_name_lc); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -1950,7 +1934,7 @@ private function checkMethodParamReferences(ClassLikeStorage $classlike_storage) try { $declaring_classlike_storage = $this->classlike_storage_provider->get($declaring_fq_classlike_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -2019,7 +2003,7 @@ private function findPossibleMethodParamTypes(ClassLikeStorage $classlike_storag try { $declaring_classlike_storage = $this->classlike_storage_provider->get($declaring_fq_classlike_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -2385,7 +2369,7 @@ public function getStorageFor(string $fq_class_name): ?ClassLikeStorage try { return $this->classlike_storage_provider->get($fq_class_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return null; } } diff --git a/src/Psalm/Internal/Codebase/DataFlowGraph.php b/src/Psalm/Internal/Codebase/DataFlowGraph.php index e07a73d53f5..f94d6f74a83 100644 --- a/src/Psalm/Internal/Codebase/DataFlowGraph.php +++ b/src/Psalm/Internal/Codebase/DataFlowGraph.php @@ -12,8 +12,8 @@ use function array_reverse; use function array_sum; use function count; +use function str_starts_with; use function strlen; -use function strpos; use function substr; /** @@ -71,7 +71,7 @@ protected static function shouldIgnoreFetch( // arraykey-fetch requires a matching arraykey-assignment at the same level // otherwise the tainting is not valid - if (strpos($path_type, $expression_type . '-fetch-') === 0 + if (str_starts_with($path_type, $expression_type . '-fetch-') || ($path_type === 'arraykey-fetch' && $expression_type === 'arrayvalue') ) { $fetch_nesting = 0; @@ -87,11 +87,11 @@ protected static function shouldIgnoreFetch( $fetch_nesting--; } - if (strpos($previous_path_type, $expression_type . '-fetch') === 0) { + if (str_starts_with($previous_path_type, $expression_type . '-fetch')) { $fetch_nesting++; } - if (strpos($previous_path_type, $expression_type . '-assignment-') === 0) { + if (str_starts_with($previous_path_type, $expression_type . '-assignment-')) { if ($fetch_nesting > 0) { $fetch_nesting--; continue; diff --git a/src/Psalm/Internal/Codebase/Functions.php b/src/Psalm/Internal/Codebase/Functions.php index 2cb3ffefd88..8178610016f 100644 --- a/src/Psalm/Internal/Codebase/Functions.php +++ b/src/Psalm/Internal/Codebase/Functions.php @@ -30,7 +30,9 @@ use function in_array; use function is_bool; use function rtrim; -use function strpos; +use function str_contains; +use function str_ends_with; +use function str_starts_with; use function strtolower; use function substr; @@ -39,8 +41,6 @@ */ final class Functions { - private FileStorageProvider $file_storage_provider; - /** * @var array */ @@ -54,12 +54,8 @@ final class Functions public DynamicFunctionStorageProvider $dynamic_storage_provider; - private Reflection $reflection; - - public function __construct(FileStorageProvider $storage_provider, Reflection $reflection) + public function __construct(private readonly FileStorageProvider $file_storage_provider, private readonly Reflection $reflection) { - $this->file_storage_provider = $storage_provider; - $this->reflection = $reflection; $this->return_type_provider = new FunctionReturnTypeProvider(); $this->existence_provider = new FunctionExistenceProvider(); $this->params_provider = new FunctionParamsProvider(); @@ -238,7 +234,7 @@ public function getFullyQualifiedFunctionNameFromString(string $function_name, S $imported_function_namespaces = $aliases->functions; $imported_namespaces = $aliases->uses; - if (strpos($function_name, '\\') !== false) { + if (str_contains($function_name, '\\')) { $function_name_parts = explode('\\', $function_name); $first_namespace = array_shift($function_name_parts); $first_namespace_lcase = strtolower($first_namespace); @@ -311,10 +307,10 @@ public function getMatchingFunctionNames( if ($current_namespace_aliases) { foreach ($current_namespace_aliases->functions as $alias_name => $function_name) { - if (strpos($alias_name, $stub) === 0) { + if (str_starts_with($alias_name, $stub)) { try { $match_function_patterns[] = $function_name; - } catch (Exception $e) { + } catch (Exception) { } } } @@ -335,8 +331,8 @@ public function getMatchingFunctionNames( foreach ($match_function_patterns as $pattern) { $pattern_lc = strtolower($pattern); - if (substr($pattern, -1, 1) === '*') { - if (strpos($function_name, rtrim($pattern_lc, '*')) !== 0) { + if (str_ends_with($pattern, '*')) { + if (!str_starts_with($function_name, rtrim($pattern_lc, '*'))) { continue; } } elseif ($function_name !== $pattern) { @@ -406,11 +402,11 @@ public function isCallMapFunctionPure( } } - if (strpos($function_id, 'image') === 0) { + if (str_starts_with($function_id, 'image')) { return false; } - if (strpos($function_id, 'readline') === 0) { + if (str_starts_with($function_id, 'readline')) { return false; } @@ -440,7 +436,7 @@ public function isCallMapFunctionPure( try { return $codebase->methods->getStorage($count_method_id)->mutation_free; - } catch (Exception $e) { + } catch (Exception) { // do nothing } } diff --git a/src/Psalm/Internal/Codebase/InternalCallMapHandler.php b/src/Psalm/Internal/Codebase/InternalCallMapHandler.php index 7bf56f42fbc..70a435b814d 100644 --- a/src/Psalm/Internal/Codebase/InternalCallMapHandler.php +++ b/src/Psalm/Internal/Codebase/InternalCallMapHandler.php @@ -24,8 +24,9 @@ use function count; use function dirname; use function file_exists; +use function str_ends_with; +use function str_starts_with; use function strlen; -use function strpos; use function strtolower; use function substr; use function version_compare; @@ -271,12 +272,12 @@ public static function getCallablesFromCallMap(string $function_id): ?array $by_reference = true; } - if (substr($arg_name, -1) === '=') { + if (str_ends_with($arg_name, '=')) { $arg_name = substr($arg_name, 0, -1); $optional = true; } - if (strpos($arg_name, '...') === 0) { + if (str_starts_with($arg_name, '...')) { $arg_name = substr($arg_name, 3); $variadic = true; } diff --git a/src/Psalm/Internal/Codebase/Methods.php b/src/Psalm/Internal/Codebase/Methods.php index bdcf71befc6..8fcf208cef3 100644 --- a/src/Psalm/Internal/Codebase/Methods.php +++ b/src/Psalm/Internal/Codebase/Methods.php @@ -57,14 +57,8 @@ */ final class Methods { - private ClassLikeStorageProvider $classlike_storage_provider; - public bool $collect_locations = false; - public FileReferenceProvider $file_reference_provider; - - private ClassLikes $classlikes; - public MethodReturnTypeProvider $return_type_provider; public MethodParamsProvider $params_provider; @@ -74,13 +68,10 @@ final class Methods public MethodVisibilityProvider $visibility_provider; public function __construct( - ClassLikeStorageProvider $storage_provider, - FileReferenceProvider $file_reference_provider, - ClassLikes $classlikes, + private readonly ClassLikeStorageProvider $classlike_storage_provider, + public FileReferenceProvider $file_reference_provider, + private readonly ClassLikes $classlikes, ) { - $this->classlike_storage_provider = $storage_provider; - $this->file_reference_provider = $file_reference_provider; - $this->classlikes = $classlikes; $this->return_type_provider = new MethodReturnTypeProvider(); $this->existence_provider = new MethodExistenceProvider(); $this->visibility_provider = new MethodVisibilityProvider(); @@ -125,7 +116,7 @@ public function methodExists( try { $class_storage = $this->classlike_storage_provider->get($fq_class_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return false; } @@ -810,7 +801,7 @@ public function getMethodReturnType( $overridden_storage_return_type, $source_analyzer->getCodebase(), ); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // TODO: fix } } else { @@ -1156,7 +1147,7 @@ public function hasStorage(MethodIdentifier $method_id): bool { try { $class_storage = $this->classlike_storage_provider->get($method_id->fq_class_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return false; } diff --git a/src/Psalm/Internal/Codebase/Populator.php b/src/Psalm/Internal/Codebase/Populator.php index 37688a034ea..dc5c9ac7dc4 100644 --- a/src/Psalm/Internal/Codebase/Populator.php +++ b/src/Psalm/Internal/Codebase/Populator.php @@ -46,33 +46,13 @@ */ final class Populator { - private ClassLikeStorageProvider $classlike_storage_provider; - - private FileStorageProvider $file_storage_provider; - /** * @var array> */ private array $invalid_class_storages = []; - private Progress $progress; - - private ClassLikes $classlikes; - - private FileReferenceProvider $file_reference_provider; - - public function __construct( - ClassLikeStorageProvider $classlike_storage_provider, - FileStorageProvider $file_storage_provider, - ClassLikes $classlikes, - FileReferenceProvider $file_reference_provider, - Progress $progress, - ) { - $this->classlike_storage_provider = $classlike_storage_provider; - $this->file_storage_provider = $file_storage_provider; - $this->classlikes = $classlikes; - $this->progress = $progress; - $this->file_reference_provider = $file_reference_provider; + public function __construct(private ClassLikeStorageProvider $classlike_storage_provider, private readonly FileStorageProvider $file_storage_provider, private readonly ClassLikes $classlikes, private readonly FileReferenceProvider $file_reference_provider, private readonly Progress $progress) + { } public function populateCodebase(): void @@ -97,7 +77,7 @@ public function populateCodebase(): void foreach ($class_storage->dependent_classlikes as $dependent_classlike_lc => $_) { try { $dependee_storage = $this->classlike_storage_provider->get($dependent_classlike_lc); - } catch (InvalidArgumentException $exception) { + } catch (InvalidArgumentException) { continue; } @@ -286,7 +266,7 @@ private function populateOverriddenMethods( ), ); $implemented_interface_storage = $storage_provider->get($implemented_interface); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -437,7 +417,7 @@ private function populateDataFromTrait( ), ); $trait_storage = $storage_provider->get($used_trait_lc); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return; } @@ -501,7 +481,7 @@ private function populateDataFromParentClass( try { $parent_storage = $storage_provider->get($parent_storage_class); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { $this->progress->debug('Populator could not find dependency (' . __LINE__ . ")\n"); $storage->invalid_dependencies[$parent_storage_class] = true; @@ -513,32 +493,26 @@ private function populateDataFromParentClass( $this->populateClassLikeStorage($parent_storage, $dependent_classlikes); - $storage->parent_classes = array_merge($storage->parent_classes, $parent_storage->parent_classes); + $storage->parent_classes = [...$storage->parent_classes, ...$parent_storage->parent_classes]; self::extendTemplateParams($storage, $parent_storage, true); $this->inheritMethodsFromParent($storage, $parent_storage); $this->inheritPropertiesFromParent($storage, $parent_storage); - $storage->class_implements = array_merge($storage->class_implements, $parent_storage->class_implements); - $storage->invalid_dependencies = array_merge( - $storage->invalid_dependencies, - $parent_storage->invalid_dependencies, - ); + $storage->class_implements = [...$storage->class_implements, ...$parent_storage->class_implements]; + $storage->invalid_dependencies = [...$storage->invalid_dependencies, ...$parent_storage->invalid_dependencies]; if ($parent_storage->has_visitor_issues) { $storage->has_visitor_issues = true; } - $storage->constants = array_merge( - array_filter( - $parent_storage->constants, - static fn(ClassConstantStorage $constant): bool - => $constant->visibility === ClassLikeAnalyzer::VISIBILITY_PUBLIC - || $constant->visibility === ClassLikeAnalyzer::VISIBILITY_PROTECTED, - ), - $storage->constants, - ); + $storage->constants = [...array_filter( + $parent_storage->constants, + static fn(ClassConstantStorage $constant): bool + => $constant->visibility === ClassLikeAnalyzer::VISIBILITY_PUBLIC + || $constant->visibility === ClassLikeAnalyzer::VISIBILITY_PROTECTED, + ), ...$storage->constants]; if ($parent_storage->preserve_constructor_signature) { $storage->preserve_constructor_signature = true; @@ -575,19 +549,13 @@ private function populateInterfaceData( $this->populateClassLikeStorage($interface_storage, $dependent_classlikes); // copy over any constants - $storage->constants = array_merge( - array_filter( - $interface_storage->constants, - static fn(ClassConstantStorage $constant): bool - => $constant->visibility === ClassLikeAnalyzer::VISIBILITY_PUBLIC, - ), - $storage->constants, - ); + $storage->constants = [...array_filter( + $interface_storage->constants, + static fn(ClassConstantStorage $constant): bool + => $constant->visibility === ClassLikeAnalyzer::VISIBILITY_PUBLIC, + ), ...$storage->constants]; - $storage->invalid_dependencies = array_merge( - $storage->invalid_dependencies, - $interface_storage->invalid_dependencies, - ); + $storage->invalid_dependencies = [...$storage->invalid_dependencies, ...$interface_storage->invalid_dependencies]; self::extendTemplateParams($storage, $interface_storage, false); @@ -601,7 +569,7 @@ private function populateInterfaceData( ), ); $new_parent_interface_storage = $storage_provider->get($new_parent); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -681,7 +649,7 @@ private function populateInterfaceDataFromParentInterface( ), ); $parent_interface_storage = $storage_provider->get($parent_interface_lc); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { $this->progress->debug('Populator could not find dependency (' . __LINE__ . ")\n"); $storage->invalid_dependencies[$parent_interface_lc] = true; @@ -695,10 +663,7 @@ private function populateInterfaceDataFromParentInterface( $storage->pseudo_methods += $parent_interface_storage->pseudo_methods; $storage->declaring_pseudo_method_ids += $parent_interface_storage->declaring_pseudo_method_ids; - $storage->parent_interfaces = array_merge( - $parent_interface_storage->parent_interfaces, - $storage->parent_interfaces, - ); + $storage->parent_interfaces = [...$parent_interface_storage->parent_interfaces, ...$storage->parent_interfaces]; if (isset($storage->parent_interfaces[strtolower(UnitEnum::class)])) { $storage->declaring_property_ids['name'] = $storage->name; @@ -727,7 +692,7 @@ private function populateDataFromImplementedInterface( ), ); $implemented_interface_storage = $storage_provider->get($implemented_interface_lc); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { $this->progress->debug('Populator could not find dependency (' . __LINE__ . ")\n"); $storage->invalid_dependencies[$implemented_interface_lc] = true; @@ -741,10 +706,7 @@ private function populateDataFromImplementedInterface( $dependent_classlikes, ); - $storage->class_implements = array_merge( - $storage->class_implements, - $implemented_interface_storage->parent_interfaces, - ); + $storage->class_implements = [...$storage->class_implements, ...$implemented_interface_storage->parent_interfaces]; } /** @@ -769,7 +731,7 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file foreach ($storage->required_file_paths as $included_file_path => $_) { try { $included_file_storage = $this->file_storage_provider->get($included_file_path); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -781,19 +743,13 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file foreach ($all_required_file_paths as $included_file_path => $_) { try { $included_file_storage = $this->file_storage_provider->get($included_file_path); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } - $storage->declaring_function_ids = array_merge( - $included_file_storage->declaring_function_ids, - $storage->declaring_function_ids, - ); + $storage->declaring_function_ids = [...$included_file_storage->declaring_function_ids, ...$storage->declaring_function_ids]; - $storage->declaring_constants = array_merge( - $included_file_storage->declaring_constants, - $storage->declaring_constants, - ); + $storage->declaring_constants = [...$included_file_storage->declaring_constants, ...$storage->declaring_constants]; } foreach ($storage->referenced_classlikes as $fq_class_name) { @@ -809,14 +765,14 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file try { $included_file_storage = $this->file_storage_provider->get($classlike_storage->location->file_path); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } foreach ($classlike_storage->used_traits as $used_trait) { try { $trait_storage = $this->classlike_storage_provider->get($used_trait); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -828,20 +784,14 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file $included_trait_file_storage = $this->file_storage_provider->get( $trait_storage->location->file_path, ); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } - $storage->declaring_function_ids = array_merge( - $included_trait_file_storage->declaring_function_ids, - $storage->declaring_function_ids, - ); + $storage->declaring_function_ids = [...$included_trait_file_storage->declaring_function_ids, ...$storage->declaring_function_ids]; } - $storage->declaring_function_ids = array_merge( - $included_file_storage->declaring_function_ids, - $storage->declaring_function_ids, - ); + $storage->declaring_function_ids = [...$included_file_storage->declaring_function_ids, ...$storage->declaring_function_ids]; } $storage->required_file_paths = $all_required_file_paths; @@ -849,7 +799,7 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file foreach ($all_required_file_paths as $required_file_path) { try { $required_file_storage = $this->file_storage_provider->get($required_file_path); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -859,7 +809,7 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file foreach ($storage->required_classes as $required_classlike) { try { $classlike_storage = $this->classlike_storage_provider->get($required_classlike); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -869,7 +819,7 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file try { $required_file_storage = $this->file_storage_provider->get($classlike_storage->location->file_path); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } @@ -933,10 +883,7 @@ protected function inheritMethodsFromParent( if ($parent_storage->is_trait && $storage->trait_alias_map ) { - $aliased_method_names = array_merge( - $aliased_method_names, - array_keys($storage->trait_alias_map, $method_name_lc, true), - ); + $aliased_method_names = [...$aliased_method_names, ...array_keys($storage->trait_alias_map, $method_name_lc, true)]; } foreach ($aliased_method_names as $aliased_method_name) { @@ -1003,10 +950,7 @@ protected function inheritMethodsFromParent( if ($parent_storage->is_trait && $storage->trait_alias_map ) { - $aliased_method_names = array_merge( - $aliased_method_names, - array_keys($storage->trait_alias_map, $method_name_lc, true), - ); + $aliased_method_names = [...$aliased_method_names, ...array_keys($storage->trait_alias_map, $method_name_lc, true)]; } foreach ($aliased_method_names as $aliased_method_name) { diff --git a/src/Psalm/Internal/Codebase/Properties.php b/src/Psalm/Internal/Codebase/Properties.php index 4547721fe1b..e8ed2cf2dc4 100644 --- a/src/Psalm/Internal/Codebase/Properties.php +++ b/src/Psalm/Internal/Codebase/Properties.php @@ -27,14 +27,8 @@ */ final class Properties { - private ClassLikeStorageProvider $classlike_storage_provider; - - private ClassLikes $classlikes; - public bool $collect_locations = false; - public FileReferenceProvider $file_reference_provider; - public PropertyExistenceProvider $property_existence_provider; public PropertyTypeProvider $property_type_provider; @@ -43,16 +37,13 @@ final class Properties public function __construct( - ClassLikeStorageProvider $storage_provider, - FileReferenceProvider $file_reference_provider, - ClassLikes $classlikes, + private readonly ClassLikeStorageProvider $classlike_storage_provider, + public FileReferenceProvider $file_reference_provider, + private readonly ClassLikes $classlikes, ) { - $this->classlike_storage_provider = $storage_provider; - $this->file_reference_provider = $file_reference_provider; $this->property_existence_provider = new PropertyExistenceProvider(); $this->property_visibility_provider = new PropertyVisibilityProvider(); $this->property_type_provider = new PropertyTypeProvider(); - $this->classlikes = $classlikes; } /** diff --git a/src/Psalm/Internal/Codebase/Reflection.php b/src/Psalm/Internal/Codebase/Reflection.php index d4c083641f5..c132d2bce57 100644 --- a/src/Psalm/Internal/Codebase/Reflection.php +++ b/src/Psalm/Internal/Codebase/Reflection.php @@ -30,7 +30,6 @@ use function array_map; use function array_merge; -use function get_class; use function implode; use function strtolower; @@ -41,19 +40,13 @@ */ final class Reflection { - private ClassLikeStorageProvider $storage_provider; - - private Codebase $codebase; - /** * @var array */ private static array $builtin_functions = []; - public function __construct(ClassLikeStorageProvider $storage_provider, Codebase $codebase) + public function __construct(private readonly ClassLikeStorageProvider $storage_provider, private readonly Codebase $codebase) { - $this->storage_provider = $storage_provider; - $this->codebase = $codebase; self::$builtin_functions = []; } @@ -71,7 +64,7 @@ public function registerClass(ReflectionClass $reflected_class): void $this->storage_provider->get($class_name_lower); return; - } catch (Exception $e) { + } catch (Exception) { // this is fine } @@ -411,7 +404,7 @@ public function registerFunction(string $function_id): ?bool } $storage->cased_name = $reflection_function->getName(); - } catch (ReflectionException $e) { + } catch (ReflectionException) { return false; } @@ -436,7 +429,7 @@ public static function getPsalmTypeFromReflectionType(?ReflectionType $reflectio ), ); } else { - throw new LogicException('Unexpected reflection class ' . get_class($reflection_type) . ' found.'); + throw new LogicException('Unexpected reflection class ' . $reflection_type::class . ' found.'); } if ($reflection_type->allowsNull()) { diff --git a/src/Psalm/Internal/Codebase/Scanner.php b/src/Psalm/Internal/Codebase/Scanner.php index aaa5e5c6aea..9359934e3d5 100644 --- a/src/Psalm/Internal/Codebase/Scanner.php +++ b/src/Psalm/Internal/Codebase/Scanner.php @@ -35,6 +35,7 @@ use function file_exists; use function min; use function realpath; +use function str_ends_with; use function strtolower; use function substr; @@ -87,8 +88,6 @@ */ final class Scanner { - private Codebase $codebase; - /** * @var array */ @@ -134,36 +133,10 @@ final class Scanner */ private array $reflected_classlikes_lc = []; - private Reflection $reflection; - - private Config $config; - - private Progress $progress; - - private FileStorageProvider $file_storage_provider; - - private FileProvider $file_provider; - - private FileReferenceProvider $file_reference_provider; - private bool $is_forked = false; - public function __construct( - Codebase $codebase, - Config $config, - FileStorageProvider $file_storage_provider, - FileProvider $file_provider, - Reflection $reflection, - FileReferenceProvider $file_reference_provider, - Progress $progress, - ) { - $this->codebase = $codebase; - $this->reflection = $reflection; - $this->file_provider = $file_provider; - $this->progress = $progress; - $this->file_storage_provider = $file_storage_provider; - $this->config = $config; - $this->file_reference_provider = $file_reference_provider; + public function __construct(private readonly Codebase $codebase, private readonly Config $config, private readonly FileStorageProvider $file_storage_provider, private readonly FileProvider $file_provider, private readonly Reflection $reflection, private readonly FileReferenceProvider $file_reference_provider, private readonly Progress $progress) + { } /** @@ -241,7 +214,7 @@ public function queueClassLikeForScanning( } // avoid checking classes that we know will just end in failure - if ($fq_classlike_name_lc === 'null' || substr($fq_classlike_name_lc, -5) === '\null') { + if ($fq_classlike_name_lc === 'null' || str_ends_with($fq_classlike_name_lc, '\null')) { return; } @@ -302,7 +275,7 @@ private function scanFilePaths(int $pool_size): bool { $files_to_scan = array_filter( $this->files_to_scan, - [$this, 'shouldScan'], + $this->shouldScan(...), ); $this->files_to_scan = []; @@ -349,7 +322,7 @@ function (): void { $this->progress->debug('Have initialised forked process for scanning' . PHP_EOL); }, - Closure::fromCallable([$this, 'scanAPath']), + Closure::fromCallable($this->scanAPath(...)), /** * @return PoolData */ @@ -682,7 +655,7 @@ function () use ($fq_class_name): ?ReflectionClass { /** @psalm-suppress ArgumentTypeCoercion */ return new ReflectionClass($fq_class_name); - } catch (Throwable $e) { + } catch (Throwable) { // do not cache any results here (as case-sensitive filenames can screw things up) return null; diff --git a/src/Psalm/Internal/Codebase/StorageByPatternResolver.php b/src/Psalm/Internal/Codebase/StorageByPatternResolver.php index f075fd81895..67a70a72003 100644 --- a/src/Psalm/Internal/Codebase/StorageByPatternResolver.php +++ b/src/Psalm/Internal/Codebase/StorageByPatternResolver.php @@ -10,8 +10,8 @@ use function preg_match; use function sprintf; +use function str_contains; use function str_replace; -use function strpos; /** * @internal @@ -30,7 +30,7 @@ public function resolveConstants( ): array { $constants = $class_like_storage->constants; - if (strpos($pattern, '*') === false) { + if (!str_contains($pattern, '*')) { if (isset($constants[$pattern])) { return [$pattern => $constants[$pattern]]; } @@ -62,7 +62,7 @@ public function resolveEnums( string $pattern, ): array { $enum_cases = $class_like_storage->enum_cases; - if (strpos($pattern, '*') === false) { + if (!str_contains($pattern, '*')) { if (isset($enum_cases[$pattern])) { return [$pattern => $enum_cases[$pattern]]; } diff --git a/src/Psalm/Internal/Codebase/TaintFlowGraph.php b/src/Psalm/Internal/Codebase/TaintFlowGraph.php index 5c5f72173eb..da5ae6de9ce 100644 --- a/src/Psalm/Internal/Codebase/TaintFlowGraph.php +++ b/src/Psalm/Internal/Codebase/TaintFlowGraph.php @@ -224,15 +224,12 @@ public function connectSinksAndSources(): void $generated_sources = $this->getSpecializedSources($source); foreach ($generated_sources as $generated_source) { - $new_sources = array_merge( - $new_sources, - $this->getChildNodes( - $generated_source, - $source_taints, - $sinks, - $visited_source_ids, - ), - ); + $new_sources = [...$new_sources, ...$this->getChildNodes( + $generated_source, + $source_taints, + $sinks, + $visited_source_ids, + )]; } } @@ -317,168 +314,116 @@ private function getChildNodes( . ' -> ' . $this->getSuccessorPath($sinks[$to_id]); foreach ($matching_taints as $matching_taint) { - switch ($matching_taint) { - case TaintKind::INPUT_CALLABLE: - $issue = new TaintedCallable( - 'Detected tainted text', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_UNSERIALIZE: - $issue = new TaintedUnserialize( - 'Detected tainted code passed to unserialize or similar', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_INCLUDE: - $issue = new TaintedInclude( - 'Detected tainted code passed to include or similar', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_EVAL: - $issue = new TaintedEval( - 'Detected tainted code passed to eval or similar', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_SQL: - $issue = new TaintedSql( - 'Detected tainted SQL', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_HTML: - $issue = new TaintedHtml( - 'Detected tainted HTML', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_HAS_QUOTES: - $issue = new TaintedTextWithQuotes( - 'Detected tainted text with possible quotes', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_SHELL: - $issue = new TaintedShell( - 'Detected tainted shell code', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::USER_SECRET: - $issue = new TaintedUserSecret( - 'Detected tainted user secret leaking', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::SYSTEM_SECRET: - $issue = new TaintedSystemSecret( - 'Detected tainted system secret leaking', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_SSRF: - $issue = new TaintedSSRF( - 'Detected tainted network request', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_LDAP: - $issue = new TaintedLdap( - 'Detected tainted LDAP request', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_COOKIE: - $issue = new TaintedCookie( - 'Detected tainted cookie', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_FILE: - $issue = new TaintedFile( - 'Detected tainted file handling', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_HEADER: - $issue = new TaintedHeader( - 'Detected tainted header', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_XPATH: - $issue = new TaintedXpath( - 'Detected tainted xpath query', - $issue_location, - $issue_trace, - $path, - ); - break; - - case TaintKind::INPUT_SLEEP: - $issue = new TaintedSleep( - 'Detected tainted sleep', - $issue_location, - $issue_trace, - $path, - ); - break; - - default: - $issue = new TaintedCustom( - 'Detected tainted ' . $matching_taint, - $issue_location, - $issue_trace, - $path, - ); - } + $issue = match ($matching_taint) { + TaintKind::INPUT_CALLABLE => new TaintedCallable( + 'Detected tainted text', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_UNSERIALIZE => new TaintedUnserialize( + 'Detected tainted code passed to unserialize or similar', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_INCLUDE => new TaintedInclude( + 'Detected tainted code passed to include or similar', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_EVAL => new TaintedEval( + 'Detected tainted code passed to eval or similar', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_SQL => new TaintedSql( + 'Detected tainted SQL', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_HTML => new TaintedHtml( + 'Detected tainted HTML', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_HAS_QUOTES => new TaintedTextWithQuotes( + 'Detected tainted text with possible quotes', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_SHELL => new TaintedShell( + 'Detected tainted shell code', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::USER_SECRET => new TaintedUserSecret( + 'Detected tainted user secret leaking', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::SYSTEM_SECRET => new TaintedSystemSecret( + 'Detected tainted system secret leaking', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_SSRF => new TaintedSSRF( + 'Detected tainted network request', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_LDAP => new TaintedLdap( + 'Detected tainted LDAP request', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_COOKIE => new TaintedCookie( + 'Detected tainted cookie', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_FILE => new TaintedFile( + 'Detected tainted file handling', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_HEADER => new TaintedHeader( + 'Detected tainted header', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_XPATH => new TaintedXpath( + 'Detected tainted xpath query', + $issue_location, + $issue_trace, + $path, + ), + TaintKind::INPUT_SLEEP => new TaintedSleep( + 'Detected tainted sleep', + $issue_location, + $issue_trace, + $path, + ), + default => new TaintedCustom( + 'Detected tainted ' . $matching_taint, + $issue_location, + $issue_trace, + $path, + ), + }; IssueBuffer::maybeAdd($issue); } @@ -543,7 +488,7 @@ private function getSpecializedSources(DataFlowNode $source): array return array_filter( $generated_sources, - [$this, 'doesForwardEdgeExist'], + $this->doesForwardEdgeExist(...), ); } diff --git a/src/Psalm/Internal/Codebase/VariableUseGraph.php b/src/Psalm/Internal/Codebase/VariableUseGraph.php index 711dc6882d3..f17154c5a1f 100644 --- a/src/Psalm/Internal/Codebase/VariableUseGraph.php +++ b/src/Psalm/Internal/Codebase/VariableUseGraph.php @@ -9,7 +9,6 @@ use Psalm\Internal\DataFlow\Path; use function abs; -use function array_merge; use function count; /** @@ -85,10 +84,7 @@ public function isVariableUsed(DataFlowNode $assignment_node): bool return true; } - $new_child_nodes = array_merge( - $new_child_nodes, - $child_nodes, - ); + $new_child_nodes = [...$new_child_nodes, ...$child_nodes]; } $sources = $new_child_nodes; diff --git a/src/Psalm/Internal/DataFlow/DataFlowNode.php b/src/Psalm/Internal/DataFlow/DataFlowNode.php index 024cc000c73..c538d3518b8 100644 --- a/src/Psalm/Internal/DataFlow/DataFlowNode.php +++ b/src/Psalm/Internal/DataFlow/DataFlowNode.php @@ -5,6 +5,7 @@ namespace Psalm\Internal\DataFlow; use Psalm\CodeLocation; +use Stringable; use function strtolower; @@ -12,21 +13,12 @@ * @psalm-consistent-constructor * @internal */ -class DataFlowNode +class DataFlowNode implements Stringable { - public string $id; - public ?string $unspecialized_id = null; - public string $label; - - public ?CodeLocation $code_location = null; - public ?string $specialization_key = null; - /** @var array */ - public array $taints; - /** @var ?self */ public ?DataFlowNode $previous = null; @@ -42,23 +34,17 @@ class DataFlowNode * @param array $taints */ public function __construct( - string $id, - string $label, - ?CodeLocation $code_location, + public string $id, + public string $label, + public ?CodeLocation $code_location, ?string $specialization_key = null, - array $taints = [], + public array $taints = [], ) { - $this->id = $id; - if ($specialization_key) { $this->unspecialized_id = $id; $this->id .= '-' . $specialization_key; } - - $this->label = $label; - $this->code_location = $code_location; $this->specialization_key = $specialization_key; - $this->taints = $taints; } /** diff --git a/src/Psalm/Internal/DataFlow/Path.php b/src/Psalm/Internal/DataFlow/Path.php index 6e233f66e0d..083ac990601 100644 --- a/src/Psalm/Internal/DataFlow/Path.php +++ b/src/Psalm/Internal/DataFlow/Path.php @@ -14,29 +14,11 @@ final class Path { use ImmutableNonCloneableTrait; - public string $type; - - /** @var ?array */ - public ?array $unescaped_taints = null; - - /** @var ?array */ - public ?array $escaped_taints = null; - - public int $length; - /** * @param ?array $unescaped_taints * @param ?array $escaped_taints */ - public function __construct( - string $type, - int $length, - ?array $unescaped_taints = null, - ?array $escaped_taints = null, - ) { - $this->type = $type; - $this->length = $length; - $this->unescaped_taints = $unescaped_taints; - $this->escaped_taints = $escaped_taints; + public function __construct(public string $type, public int $length, public ?array $unescaped_taints = null, public ?array $escaped_taints = null) + { } } diff --git a/src/Psalm/Internal/Diff/ClassStatementsDiffer.php b/src/Psalm/Internal/Diff/ClassStatementsDiffer.php index f28cbae4936..d2e2914096d 100644 --- a/src/Psalm/Internal/Diff/ClassStatementsDiffer.php +++ b/src/Psalm/Internal/Diff/ClassStatementsDiffer.php @@ -7,8 +7,7 @@ use PhpParser; use function count; -use function get_class; -use function strpos; +use function str_contains; use function strtolower; use function substr; use function trim; @@ -43,7 +42,7 @@ static function ( string $b_code, bool &$body_change = false, ) use (&$diff_map): bool { - if (get_class($a) !== get_class($b)) { + if ($a::class !== $b::class) { return false; } @@ -144,8 +143,8 @@ static function ( $a_signature = trim($a_signature); $b_signature = trim($b_signature); - if (strpos($a_signature, $b_signature) === false - && strpos($b_signature, $a_signature) === false + if (!str_contains($a_signature, $b_signature) + && !str_contains($b_signature, $a_signature) ) { $signature_change = true; } diff --git a/src/Psalm/Internal/Diff/DiffElem.php b/src/Psalm/Internal/Diff/DiffElem.php index 74a993ace22..4ea886f7927 100644 --- a/src/Psalm/Internal/Diff/DiffElem.php +++ b/src/Psalm/Internal/Diff/DiffElem.php @@ -20,17 +20,13 @@ final class DiffElem public const TYPE_REPLACE = 3; public const TYPE_KEEP_SIGNATURE = 4; - /** @var int One of the TYPE_* constants */ - public int $type; - /** @var mixed Is null for add operations */ - public mixed $old; - /** @var mixed Is null for remove operations */ - public mixed $new; - - public function __construct(int $type, mixed $old, mixed $new) - { - $this->type = $type; - $this->old = $old; - $this->new = $new; + public function __construct( + /** @var int One of the TYPE_* constants */ + public int $type, + /** @var mixed Is null for add operations */ + public mixed $old, + /** @var mixed Is null for remove operations */ + public mixed $new, + ) { } } diff --git a/src/Psalm/Internal/Diff/FileDiffer.php b/src/Psalm/Internal/Diff/FileDiffer.php index e6812050b3d..e3ce3fbbd32 100644 --- a/src/Psalm/Internal/Diff/FileDiffer.php +++ b/src/Psalm/Internal/Diff/FileDiffer.php @@ -250,7 +250,7 @@ public static function getDiff(string $a_code, string $b_code): array $b_offset += $new_text_length; } else { /** @psalm-suppress MixedArgument */ - $same_text_length = strlen($diff_elem->new) + 1; + $same_text_length = strlen((string) $diff_elem->new) + 1; $a_offset += $same_text_length; $b_offset += $same_text_length; diff --git a/src/Psalm/Internal/Diff/FileStatementsDiffer.php b/src/Psalm/Internal/Diff/FileStatementsDiffer.php index c5928ae0a15..abd570b558c 100644 --- a/src/Psalm/Internal/Diff/FileStatementsDiffer.php +++ b/src/Psalm/Internal/Diff/FileStatementsDiffer.php @@ -8,7 +8,6 @@ use function assert; use function end; -use function get_class; use function substr; /** @@ -38,7 +37,7 @@ static function ( string $a_code, string $b_code, ): bool { - if (get_class($a) !== get_class($b)) { + if ($a::class !== $b::class) { return false; } diff --git a/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php b/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php index 2203ef76bfc..d16926d526a 100644 --- a/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php +++ b/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php @@ -8,7 +8,6 @@ use function assert; use function end; -use function get_class; use function substr; /** @@ -38,7 +37,7 @@ static function ( string $a_code, string $b_code, ): bool { - if (get_class($a) !== get_class($b)) { + if ($a::class !== $b::class) { return false; } diff --git a/src/Psalm/Internal/ErrorHandler.php b/src/Psalm/Internal/ErrorHandler.php index a37a78d1671..9a41edf165d 100644 --- a/src/Psalm/Internal/ErrorHandler.php +++ b/src/Psalm/Internal/ErrorHandler.php @@ -31,7 +31,7 @@ final class ErrorHandler /** * @param array $argv */ - public static function install(array $argv = array()): void + public static function install(array $argv = []): void { self::$args = implode(' ', $argv); self::setErrorReporting(); @@ -93,7 +93,7 @@ private static function installExceptionHandler(): void * then print more of the backtrace than is done by default to stderr, * then exit with a non-zero exit code to indicate failure. */ - set_exception_handler(static function (Throwable $throwable): void { + set_exception_handler(static function (Throwable $throwable): never { fwrite(STDERR, "Uncaught $throwable\n"); $version = defined('PSALM_VERSION') ? PSALM_VERSION : '(unknown version)'; fwrite(STDERR, "(Psalm $version crashed due to an uncaught Throwable)\n"); diff --git a/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php b/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php index cc820d0ec9e..aef34adfee4 100644 --- a/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php +++ b/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php @@ -11,8 +11,8 @@ use function explode; use function file_get_contents; use function json_decode; +use function str_contains; use function str_replace; -use function strpos; use function strtotime; use const JSON_THROW_ON_ERROR; @@ -25,21 +25,19 @@ */ final class BuildInfoCollector { - /** - * Environment variables. - * - * Overwritten through collection process. - */ - protected array $env; - /** * Read environment variables. */ protected array $readEnv = []; - public function __construct(array $env) - { - $this->env = $env; + public function __construct( + /** + * Environment variables. + * + * Overwritten through collection process. + */ + protected array $env, + ) { } // API @@ -260,9 +258,9 @@ protected function fillGithubActions(): BuildInfoCollector $this->env['CI_JOB_ID'] = $this->env['GITHUB_ACTIONS']; $githubRef = (string) $this->env['GITHUB_REF']; - if (strpos($githubRef, 'refs/heads/') !== false) { + if (str_contains($githubRef, 'refs/heads/')) { $githubRef = str_replace('refs/heads/', '', $githubRef); - } elseif (strpos($githubRef, 'refs/tags/') !== false) { + } elseif (str_contains($githubRef, 'refs/tags/')) { $githubRef = str_replace('refs/tags/', '', $githubRef); } diff --git a/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php b/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php index 5111b381d0b..e23f5781a06 100644 --- a/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php +++ b/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php @@ -14,7 +14,8 @@ use function count; use function explode; use function range; -use function strpos; +use function str_contains; +use function str_starts_with; use function trim; /** @@ -62,7 +63,7 @@ protected function collectBranch(): string $branchesResult = $this->executor->execute('git branch'); foreach ($branchesResult as $result) { - if (strpos($result, '* ') === 0) { + if (str_starts_with($result, '* ')) { $exploded = explode('* ', $result, 2); return $exploded[1]; @@ -115,7 +116,7 @@ protected function collectRemotes(): array $results = []; foreach ($remotesResult as $result) { - if (strpos($result, ' ') !== false) { + if (str_contains($result, ' ')) { [$remote] = explode(' ', $result, 2); $results[] = $remote; @@ -129,7 +130,7 @@ protected function collectRemotes(): array $remotes = []; foreach ($results as $result) { - if (strpos($result, "\t") !== false) { + if (str_contains($result, "\t")) { [$name, $url] = explode("\t", $result, 2); $remote = new RemoteInfo(); diff --git a/src/Psalm/Internal/FileManipulation/ClassDocblockManipulator.php b/src/Psalm/Internal/FileManipulation/ClassDocblockManipulator.php index ec44a1c3575..be08809c224 100644 --- a/src/Psalm/Internal/FileManipulation/ClassDocblockManipulator.php +++ b/src/Psalm/Internal/FileManipulation/ClassDocblockManipulator.php @@ -26,15 +26,13 @@ final class ClassDocblockManipulator */ private static array $manipulators = []; - private Class_ $stmt; + private readonly int $docblock_start; - private int $docblock_start; - - private int $docblock_end; + private readonly int $docblock_end; private bool $immutable = false; - private string $indentation; + private readonly string $indentation; public static function getForClass( ProjectAnalyzer $project_analyzer, @@ -54,10 +52,9 @@ public static function getForClass( private function __construct( ProjectAnalyzer $project_analyzer, - Class_ $stmt, + private readonly Class_ $stmt, string $file_path, ) { - $this->stmt = $stmt; $docblock = $stmt->getDocComment(); $this->docblock_start = $docblock ? $docblock->getStartFilePos() : (int)$stmt->getAttribute('startFilePos'); $this->docblock_end = (int)$stmt->getAttribute('startFilePos'); diff --git a/src/Psalm/Internal/FileManipulation/CodeMigration.php b/src/Psalm/Internal/FileManipulation/CodeMigration.php index 9c703dea506..61ca6230fb2 100644 --- a/src/Psalm/Internal/FileManipulation/CodeMigration.php +++ b/src/Psalm/Internal/FileManipulation/CodeMigration.php @@ -14,27 +14,7 @@ final class CodeMigration { use ImmutableNonCloneableTrait; - public string $source_file_path; - - public int $source_start; - - public int $source_end; - - public string $destination_file_path; - - public int $destination_start; - - public function __construct( - string $source_file_path, - int $source_start, - int $source_end, - string $destination_file_path, - int $destination_start, - ) { - $this->source_file_path = $source_file_path; - $this->source_start = $source_start; - $this->source_end = $source_end; - $this->destination_file_path = $destination_file_path; - $this->destination_start = $destination_start; + public function __construct(public string $source_file_path, public int $source_start, public int $source_end, public string $destination_file_path, public int $destination_start) + { } } diff --git a/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php b/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php index 12ac9be6ea4..9e00cc968de 100644 --- a/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php +++ b/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php @@ -17,7 +17,6 @@ use Psalm\Internal\Scanner\ParsedDocblock; use function array_key_exists; -use function array_merge; use function array_reduce; use function array_slice; use function count; @@ -45,13 +44,11 @@ final class FunctionDocblockManipulator */ private static array $manipulators = []; - private Closure|Function_|ClassMethod|ArrowFunction $stmt; + private readonly int $docblock_start; - private int $docblock_start; + private readonly int $docblock_end; - private int $docblock_end; - - private int $return_typehint_area_start; + private readonly int $return_typehint_area_start; private ?int $return_typehint_colon_start = null; @@ -110,12 +107,8 @@ public static function getForFunction( return $manipulator; } - /** - * @param Closure|Function_|ClassMethod|ArrowFunction $stmt - */ - private function __construct(string $file_path, FunctionLike $stmt, ProjectAnalyzer $project_analyzer) + private function __construct(string $file_path, private readonly Closure|Function_|ClassMethod|ArrowFunction $stmt, ProjectAnalyzer $project_analyzer) { - $this->stmt = $stmt; $docblock = $stmt->getDocComment(); $this->docblock_start = $docblock ? $docblock->getStartFilePos() : (int)$stmt->getAttribute('startFilePos'); $this->docblock_end = $function_start = (int)$stmt->getAttribute('startFilePos'); @@ -578,7 +571,7 @@ public static function clearCache(): void */ public static function addManipulators(array $manipulators): void { - self::$manipulators = array_merge($manipulators, self::$manipulators); + self::$manipulators = [...$manipulators, ...self::$manipulators]; } /** diff --git a/src/Psalm/Internal/FileManipulation/PropertyDocblockManipulator.php b/src/Psalm/Internal/FileManipulation/PropertyDocblockManipulator.php index 3f00530e5bb..6aa54dbed74 100644 --- a/src/Psalm/Internal/FileManipulation/PropertyDocblockManipulator.php +++ b/src/Psalm/Internal/FileManipulation/PropertyDocblockManipulator.php @@ -31,15 +31,13 @@ final class PropertyDocblockManipulator */ private static array $manipulators = []; - private Property $stmt; + private readonly int $docblock_start; - private int $docblock_start; - - private int $docblock_end; + private readonly int $docblock_end; private ?int $typehint_start = null; - private int $typehint_area_start; + private readonly int $typehint_area_start; private ?int $typehint_end = null; @@ -75,10 +73,9 @@ public static function getForProperty( private function __construct( ProjectAnalyzer $project_analyzer, - Property $stmt, + private readonly Property $stmt, string $file_path, ) { - $this->stmt = $stmt; $docblock = $stmt->getDocComment(); $this->docblock_start = $docblock ? $docblock->getStartFilePos() : (int)$stmt->getAttribute('startFilePos'); $this->docblock_end = (int)$stmt->getAttribute('startFilePos'); diff --git a/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php b/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php index 233c2252411..bd595572044 100644 --- a/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php +++ b/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php @@ -13,10 +13,8 @@ final class ForkProcessDoneMessage implements ForkMessage { use ImmutableNonCloneableTrait; - public mixed $data; - public function __construct(mixed $data) + public function __construct(public mixed $data) { - $this->data = $data; } } diff --git a/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php b/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php index 1c59bac6793..3bec3754a91 100644 --- a/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php +++ b/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php @@ -14,10 +14,7 @@ final class ForkProcessErrorMessage implements ForkMessage { use ImmutableNonCloneableTrait; - public string $message; - - public function __construct(string $message) + public function __construct(public string $message) { - $this->message = $message; } } diff --git a/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php b/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php index 7cc1c01a0ac..2959f472484 100644 --- a/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php +++ b/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php @@ -14,10 +14,7 @@ final class ForkTaskDoneMessage implements ForkMessage { use ImmutableNonCloneableTrait; - public mixed $data; - - public function __construct(mixed $data) + public function __construct(public mixed $data) { - $this->data = $data; } } diff --git a/src/Psalm/Internal/Fork/Pool.php b/src/Psalm/Internal/Fork/Pool.php index 6a4145aaac1..092956ed463 100644 --- a/src/Psalm/Internal/Fork/Pool.php +++ b/src/Psalm/Internal/Fork/Pool.php @@ -26,7 +26,6 @@ use function feof; use function fread; use function fwrite; -use function get_class; use function gettype; use function igbinary_serialize; use function igbinary_unserialize; @@ -41,12 +40,12 @@ use function posix_kill; use function posix_strerror; use function serialize; +use function str_contains; use function stream_select; use function stream_set_blocking; use function stream_socket_pair; use function stripos; use function strlen; -use function strpos; use function substr; use function unserialize; use function usleep; @@ -77,8 +76,6 @@ final class Pool private const EXIT_SUCCESS = 0; private const EXIT_FAILURE = 1; - private Config $config; - /** @var int[] */ private array $child_pid_list = []; @@ -87,9 +84,6 @@ final class Pool private bool $did_have_error = false; - /** @var ?Closure(mixed): void */ - private ?Closure $task_done_closure = null; - public const MAC_PCRE_MESSAGE = 'Mac users: pcre.jit is set to 1 in your PHP config.' . PHP_EOL . 'The pcre jit is known to cause segfaults in PHP 7.3 on Macs, and Psalm' . PHP_EOL . 'will not execute in threaded mode to avoid indecipherable errors.' . PHP_EOL @@ -113,16 +107,14 @@ final class Pool * @psalm-suppress MixedAssignment */ public function __construct( - Config $config, + private readonly Config $config, array $process_task_data_iterator, Closure $startup_closure, Closure $task_closure, Closure $shutdown_closure, - ?Closure $task_done_closure = null, + private readonly ?Closure $task_done_closure = null, ) { $pool_size = count($process_task_data_iterator); - $this->task_done_closure = $task_done_closure; - $this->config = $config; assert( $pool_size > 1, @@ -242,7 +234,7 @@ public function __construct( // This can happen when developing Psalm from source without running `composer update`, // or because of rare bugs in Psalm. $process_done_message = new ForkProcessErrorMessage( - get_class($t) . ' ' . $t->getMessage() . "\n" . + $t::class . ' ' . $t->getMessage() . "\n" . "Emitted in " . $t->getFile() . ":" . $t->getLine() . "\n" . "Stack trace in the forked worker:\n" . $t->getTraceAsString(), @@ -368,7 +360,7 @@ private function readResultsFromChildren(): array $content[(int)$file] .= $buffer; } - if (strpos($buffer, "\n") !== false) { + if (str_contains($buffer, "\n")) { $serialized_messages = explode("\n", $content[(int)$file]); $content[(int)$file] = array_pop($serialized_messages); diff --git a/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php b/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php index 5d44d2f598e..ab212c32e84 100644 --- a/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php +++ b/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php @@ -17,13 +17,10 @@ final class LegacyProgress implements ProgressInterface private const STATUS_FINISHED = 'finished'; private string $status = self::STATUS_INACTIVE; - - private ClientHandler $handler; private ?string $title = null; - public function __construct(ClientHandler $handler) + public function __construct(private readonly ClientHandler $handler) { - $this->handler = $handler; } public function begin(string $title, ?string $message = null, ?int $percentage = null): void diff --git a/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php b/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php index 284d2bf76d1..79d04a799fc 100644 --- a/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php +++ b/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php @@ -15,15 +15,10 @@ final class Progress implements ProgressInterface private const STATUS_FINISHED = 'finished'; private string $status = self::STATUS_INACTIVE; - - private ClientHandler $handler; - private string $token; private bool $withPercentage = false; - public function __construct(ClientHandler $handler, string $token) + public function __construct(private readonly ClientHandler $handler, private readonly string $token) { - $this->handler = $handler; - $this->token = $token; } public function begin( diff --git a/src/Psalm/Internal/LanguageServer/Client/TextDocument.php b/src/Psalm/Internal/LanguageServer/Client/TextDocument.php index 1e65565df3c..b186454b915 100644 --- a/src/Psalm/Internal/LanguageServer/Client/TextDocument.php +++ b/src/Psalm/Internal/LanguageServer/Client/TextDocument.php @@ -15,14 +15,8 @@ */ final class TextDocument { - private ClientHandler $handler; - - private LanguageServer $server; - - public function __construct(ClientHandler $handler, LanguageServer $server) + public function __construct(private readonly ClientHandler $handler, private readonly LanguageServer $server) { - $this->handler = $handler; - $this->server = $server; } /** diff --git a/src/Psalm/Internal/LanguageServer/Client/Workspace.php b/src/Psalm/Internal/LanguageServer/Client/Workspace.php index e08e31192e0..eedb9431548 100644 --- a/src/Psalm/Internal/LanguageServer/Client/Workspace.php +++ b/src/Psalm/Internal/LanguageServer/Client/Workspace.php @@ -15,20 +15,14 @@ */ final class Workspace { - private ClientHandler $handler; - - /** - * @psalm-suppress UnusedProperty - */ - private JsonMapper $mapper; - - private LanguageServer $server; - - public function __construct(ClientHandler $handler, JsonMapper $mapper, LanguageServer $server) - { - $this->handler = $handler; - $this->mapper = $mapper; - $this->server = $server; + public function __construct( + private readonly ClientHandler $handler, + /** + * @psalm-suppress UnusedProperty + */ + private readonly JsonMapper $mapper, + private readonly LanguageServer $server, + ) { } /** diff --git a/src/Psalm/Internal/LanguageServer/ClientConfiguration.php b/src/Psalm/Internal/LanguageServer/ClientConfiguration.php index a2ad6193eda..00d657c66fc 100644 --- a/src/Psalm/Internal/LanguageServer/ClientConfiguration.php +++ b/src/Psalm/Internal/LanguageServer/ClientConfiguration.php @@ -12,11 +12,6 @@ final class ClientConfiguration { - /** - * Location of Baseline file - */ - public ?string $baseline = null; - /** * TCP Server Address */ @@ -27,68 +22,6 @@ final class ClientConfiguration */ public ?bool $TCPServerMode = null; - /** - * Hide Warnings or not - */ - public ?bool $hideWarnings = null; - - /** - * Provide Completion or not - */ - public ?bool $provideCompletion = null; - - /** - * Provide GoTo Definitions or not - */ - public ?bool $provideDefinition = null; - - /** - * Provide Hover Requests or not - */ - public ?bool $provideHover = null; - - /** - * Provide Signature Help or not - */ - public ?bool $provideSignatureHelp = null; - - /** - * Provide Code Actions or not - */ - public ?bool $provideCodeActions = null; - - /** - * Provide Diagnostics or not - */ - public ?bool $provideDiagnostics = null; - - /** - * Provide Completion or not - * - * @psalm-suppress PossiblyUnusedProperty - */ - public ?bool $findUnusedVariables = null; - - /** - * Look for dead code - * - * @var 'always'|'auto'|null - */ - public ?string $findUnusedCode = null; - - /** - * Log Level - * - * @see MessageType - */ - public ?int $logLevel = null; - - /** - * If added, the language server will not respond to onChange events. - * You can also specify a line count over which Psalm will not run on-change events. - */ - public ?int $onchangeLineLimit = null; - /** * Debounce time in milliseconds for onChange events */ @@ -100,30 +33,59 @@ final class ClientConfiguration * @param 'always'|'auto'|null $findUnusedCode */ public function __construct( - bool $hideWarnings = true, - ?bool $provideCompletion = null, - ?bool $provideDefinition = null, - ?bool $provideHover = null, - ?bool $provideSignatureHelp = null, - ?bool $provideCodeActions = null, - ?bool $provideDiagnostics = null, - ?bool $findUnusedVariables = null, - ?string $findUnusedCode = null, - ?int $logLevel = null, - ?int $onchangeLineLimit = null, - ?string $baseline = null, + /** + * Hide Warnings or not + */ + public ?bool $hideWarnings = true, + /** + * Provide Completion or not + */ + public ?bool $provideCompletion = null, + /** + * Provide GoTo Definitions or not + */ + public ?bool $provideDefinition = null, + /** + * Provide Hover Requests or not + */ + public ?bool $provideHover = null, + /** + * Provide Signature Help or not + */ + public ?bool $provideSignatureHelp = null, + /** + * Provide Code Actions or not + */ + public ?bool $provideCodeActions = null, + /** + * Provide Diagnostics or not + */ + public ?bool $provideDiagnostics = null, + /** + * Provide Completion or not + * + * @psalm-suppress PossiblyUnusedProperty + */ + public ?bool $findUnusedVariables = null, + /** + * Look for dead code + */ + public ?string $findUnusedCode = null, + /** + * Log Level + * + * @see MessageType + */ + public ?int $logLevel = null, + /** + * If added, the language server will not respond to onChange events. + * You can also specify a line count over which Psalm will not run on-change events. + */ + public ?int $onchangeLineLimit = null, + /** + * Location of Baseline file + */ + public ?string $baseline = null, ) { - $this->hideWarnings = $hideWarnings; - $this->provideCompletion = $provideCompletion; - $this->provideDefinition = $provideDefinition; - $this->provideHover = $provideHover; - $this->provideSignatureHelp = $provideSignatureHelp; - $this->provideCodeActions = $provideCodeActions; - $this->provideDiagnostics = $provideDiagnostics; - $this->findUnusedVariables = $findUnusedVariables; - $this->findUnusedCode = $findUnusedCode; - $this->logLevel = $logLevel; - $this->onchangeLineLimit = $onchangeLineLimit; - $this->baseline = $baseline; } } diff --git a/src/Psalm/Internal/LanguageServer/ClientHandler.php b/src/Psalm/Internal/LanguageServer/ClientHandler.php index 29d2cce6914..2b6bcc21aee 100644 --- a/src/Psalm/Internal/LanguageServer/ClientHandler.php +++ b/src/Psalm/Internal/LanguageServer/ClientHandler.php @@ -15,16 +15,10 @@ */ final class ClientHandler { - public ProtocolReader $protocolReader; - - public ProtocolWriter $protocolWriter; - public IdGenerator $idGenerator; - public function __construct(ProtocolReader $protocolReader, ProtocolWriter $protocolWriter) + public function __construct(public ProtocolReader $protocolReader, public ProtocolWriter $protocolWriter) { - $this->protocolReader = $protocolReader; - $this->protocolWriter = $protocolWriter; $this->idGenerator = new IdGenerator; } diff --git a/src/Psalm/Internal/LanguageServer/LanguageClient.php b/src/Psalm/Internal/LanguageServer/LanguageClient.php index f23985592bd..a0b15154a8e 100644 --- a/src/Psalm/Internal/LanguageServer/LanguageClient.php +++ b/src/Psalm/Internal/LanguageServer/LanguageClient.php @@ -19,6 +19,8 @@ use function json_decode; use function json_encode; +use const JSON_THROW_ON_ERROR; + /** * @internal */ @@ -37,30 +39,24 @@ final class LanguageClient /** * The client handler */ - private ClientHandler $handler; - - /** - * The Language Server - */ - private LanguageServer $server; - - /** - * The Client Configuration - */ - public ClientConfiguration $clientConfiguration; + private readonly ClientHandler $handler; public function __construct( ProtocolReader $reader, ProtocolWriter $writer, - LanguageServer $server, - ClientConfiguration $clientConfiguration, + /** + * The Language Server + */ + private readonly LanguageServer $server, + /** + * The Client Configuration + */ + public ClientConfiguration $clientConfiguration, ) { $this->handler = new ClientHandler($reader, $writer); - $this->server = $server; $this->textDocument = new ClientTextDocument($this->handler, $this->server); $this->workspace = new ClientWorkspace($this->handler, new JsonMapper, $this->server); - $this->clientConfiguration = $clientConfiguration; } /** @@ -147,8 +143,6 @@ public function makeProgress(string $token): ProgressInterface /** * Configuration Refreshed from Client - * - * @param array $config */ private function configurationRefreshed(array $config): void { @@ -159,7 +153,7 @@ private function configurationRefreshed(array $config): void } /** @var array */ - $array = json_decode((string) json_encode($config), true); + $array = json_decode((string) json_encode($config, JSON_THROW_ON_ERROR), true, 512, JSON_THROW_ON_ERROR); if (isset($array['hideWarnings'])) { $this->clientConfiguration->hideWarnings = (bool) $array['hideWarnings']; diff --git a/src/Psalm/Internal/LanguageServer/LanguageServer.php b/src/Psalm/Internal/LanguageServer/LanguageServer.php index e155881c860..30e8758c504 100644 --- a/src/Psalm/Internal/LanguageServer/LanguageServer.php +++ b/src/Psalm/Internal/LanguageServer/LanguageServer.php @@ -74,12 +74,13 @@ use function parse_url; use function rawurlencode; use function realpath; +use function str_contains; +use function str_ends_with; use function str_replace; use function stream_set_blocking; use function stream_socket_accept; use function stream_socket_client; use function stream_socket_server; -use function strpos; use function substr; use function trim; use function uniqid; @@ -108,20 +109,12 @@ final class LanguageServer extends Dispatcher public ?ClientInfo $clientInfo = null; - protected ProtocolReader $protocolReader; - - protected ProtocolWriter $protocolWriter; - public LanguageClient $client; public ?ClientCapabilities $clientCapabilities = null; public ?string $trace = null; - protected ProjectAnalyzer $project_analyzer; - - protected Codebase $codebase; - /** * The AMP Delay token */ @@ -137,33 +130,21 @@ final class LanguageServer extends Dispatcher */ protected JsonMapper $mapper; - protected PathMapper $path_mapper; - public function __construct( - ProtocolReader $reader, - ProtocolWriter $writer, - ProjectAnalyzer $project_analyzer, - Codebase $codebase, + protected ProtocolReader $protocolReader, + protected ProtocolWriter $protocolWriter, + protected ProjectAnalyzer $project_analyzer, + protected Codebase $codebase, ClientConfiguration $clientConfiguration, Progress $progress, - PathMapper $path_mapper, + protected PathMapper $path_mapper, ) { parent::__construct($this, '/'); $progress->setServer($this); - - $this->project_analyzer = $project_analyzer; - - $this->codebase = $codebase; - - $this->path_mapper = $path_mapper; - - $this->protocolWriter = $writer; - - $this->protocolReader = $reader; $this->protocolReader->on( 'close', - function (): void { + function (): never { $this->shutdown(); $this->exit(); }, @@ -225,7 +206,7 @@ function (): void { }, ); - $this->client = new LanguageClient($reader, $writer, $this, $clientConfiguration); + $this->client = new LanguageClient($protocolReader, $protocolWriter, $this, $clientConfiguration); $this->logInfo("Psalm Language Server ".PSALM_VERSION." has started."); @@ -698,14 +679,10 @@ function (IssueData $issue_data): Diagnostic { new Position($start_line - 1, $start_column - 1), new Position($end_line - 1, $end_column - 1), ); - switch ($severity) { - case IssueData::SEVERITY_INFO: - $diagnostic_severity = DiagnosticSeverity::WARNING; - break; - default: - $diagnostic_severity = DiagnosticSeverity::ERROR; - break; - } + $diagnostic_severity = match ($severity) { + IssueData::SEVERITY_INFO => DiagnosticSeverity::WARNING, + default => DiagnosticSeverity::ERROR, + }; $diagnostic = new Diagnostic( $description, $range, @@ -812,7 +789,7 @@ public function shutdown(): void * The server should exit with success code 0 if the shutdown request has been received before; * otherwise with error code 1. */ - public function exit(): void + public function exit(): never { exit(0); } @@ -852,7 +829,7 @@ public function log(int $type, string $message, array $context = []): void $message, ), ); - } catch (Throwable $err) { + } catch (Throwable) { // do nothing as we could potentially go into a loop here is not careful //TODO: Investigate if we can use error_log instead } @@ -915,7 +892,7 @@ private function clientStatus(string $status, ?string $additional_info = null): $status . (!empty($additional_info) ? ': ' . $additional_info : ''), ), ); - } catch (Throwable $err) { + } catch (Throwable) { // do nothing } } @@ -934,7 +911,7 @@ public function pathToUri(string $filepath): string $parts = explode('/', $filepath); // Don't %-encode the colon after a Windows drive letter $first = array_shift($parts); - if (substr($first, -1) !== ':') { + if (!str_ends_with($first, ':')) { $first = rawurlencode($first); } $parts = array_map('rawurlencode', $parts); @@ -951,7 +928,7 @@ public function uriToPath(string $uri): string { $filepath = urldecode($this->getPathPart($uri)); - if (strpos($filepath, ':') !== false) { + if (str_contains($filepath, ':')) { if ($filepath[0] === '/') { $filepath = substr($filepath, 1); } diff --git a/src/Psalm/Internal/LanguageServer/Message.php b/src/Psalm/Internal/LanguageServer/Message.php index 400cf9d0dbb..b0bae0c8655 100644 --- a/src/Psalm/Internal/LanguageServer/Message.php +++ b/src/Psalm/Internal/LanguageServer/Message.php @@ -5,6 +5,7 @@ namespace Psalm\Internal\LanguageServer; use AdvancedJsonRpc\Message as MessageBody; +use Stringable; use function array_pop; use function explode; @@ -13,10 +14,8 @@ /** * @internal */ -final class Message +final class Message implements Stringable { - public ?MessageBody $body = null; - /** * @var string[] */ @@ -45,9 +44,8 @@ public static function parse(string $msg): Message /** * @param string[] $headers */ - public function __construct(?MessageBody $body = null, array $headers = []) + public function __construct(public ?MessageBody $body = null, array $headers = []) { - $this->body = $body; if (!isset($headers['Content-Type'])) { $headers['Content-Type'] = 'application/vscode-jsonrpc; charset=utf8'; } diff --git a/src/Psalm/Internal/LanguageServer/PHPMarkdownContent.php b/src/Psalm/Internal/LanguageServer/PHPMarkdownContent.php index a6141a98536..b0d6303227a 100644 --- a/src/Psalm/Internal/LanguageServer/PHPMarkdownContent.php +++ b/src/Psalm/Internal/LanguageServer/PHPMarkdownContent.php @@ -17,18 +17,8 @@ */ final class PHPMarkdownContent extends MarkupContent implements JsonSerializable { - public string $code; - - public ?string $title = null; - - public ?string $description = null; - - public function __construct(string $code, ?string $title = null, ?string $description = null) + public function __construct(public string $code, public ?string $title = null, public ?string $description = null) { - $this->code = $code; - $this->title = $title; - $this->description = $description; - $markdown = ''; if ($title !== null) { $markdown = "**$title**\n\n"; diff --git a/src/Psalm/Internal/LanguageServer/PathMapper.php b/src/Psalm/Internal/LanguageServer/PathMapper.php index dbaaaf7018d..f0fd5abaffc 100644 --- a/src/Psalm/Internal/LanguageServer/PathMapper.php +++ b/src/Psalm/Internal/LanguageServer/PathMapper.php @@ -5,13 +5,14 @@ namespace Psalm\Internal\LanguageServer; use function rtrim; +use function str_starts_with; use function strlen; use function substr; /** @internal */ final class PathMapper { - private string $server_root; + private readonly string $server_root; private ?string $client_root; public function __construct(string $server_root, ?string $client_root = null) @@ -34,7 +35,7 @@ public function mapClientToServer(string $client_path): string return $client_path; } - if (substr($client_path, 0, strlen($this->client_root)) === $this->client_root) { + if (str_starts_with($client_path, $this->client_root)) { return $this->server_root . substr($client_path, strlen($this->client_root)); } @@ -46,7 +47,7 @@ public function mapServerToClient(string $server_path): string if ($this->client_root === null) { return $server_path; } - if (substr($server_path, 0, strlen($this->server_root)) === $this->server_root) { + if (str_starts_with($server_path, $this->server_root)) { return $this->client_root . substr($server_path, strlen($this->server_root)); } return $server_path; diff --git a/src/Psalm/Internal/LanguageServer/ProtocolStreamReader.php b/src/Psalm/Internal/LanguageServer/ProtocolStreamReader.php index 57422b52ee8..1e58dce1f9d 100644 --- a/src/Psalm/Internal/LanguageServer/ProtocolStreamReader.php +++ b/src/Psalm/Internal/LanguageServer/ProtocolStreamReader.php @@ -10,8 +10,8 @@ use Revolt\EventLoop; use function explode; +use function str_ends_with; use function strlen; -use function substr; use function trim; /** @@ -82,7 +82,7 @@ private function readMessages(string $buffer): int $this->parsing_mode = self::PARSE_BODY; $this->content_length = (int) ($this->headers['Content-Length'] ?? 0); $this->buffer = ''; - } elseif (substr($this->buffer, -2) === "\r\n") { + } elseif (str_ends_with($this->buffer, "\r\n")) { $parts = explode(':', $this->buffer); if (isset($parts[1])) { $this->headers[$parts[0]] = trim($parts[1]); @@ -101,7 +101,7 @@ private function readMessages(string $buffer): int // MessageBody::parse can throw an Error, maybe log an error? try { $msg = new Message(MessageBody::parse($this->buffer), $this->headers); - } catch (Exception $_) { + } catch (Exception) { $msg = null; } if ($msg) { diff --git a/src/Psalm/Internal/LanguageServer/ProtocolStreamWriter.php b/src/Psalm/Internal/LanguageServer/ProtocolStreamWriter.php index 69405637577..2010816fd6a 100644 --- a/src/Psalm/Internal/LanguageServer/ProtocolStreamWriter.php +++ b/src/Psalm/Internal/LanguageServer/ProtocolStreamWriter.php @@ -11,7 +11,7 @@ */ final class ProtocolStreamWriter implements ProtocolWriter { - private WritableResourceStream $output; + private readonly WritableResourceStream $output; /** * @param resource $output diff --git a/src/Psalm/Internal/LanguageServer/Provider/ParserCacheProvider.php b/src/Psalm/Internal/LanguageServer/Provider/ParserCacheProvider.php index 47861abe470..6d988869a97 100644 --- a/src/Psalm/Internal/LanguageServer/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/LanguageServer/Provider/ParserCacheProvider.php @@ -58,11 +58,7 @@ public function loadStatementsFromCache( */ public function loadExistingStatementsFromCache(string $file_path): ?array { - if (isset($this->statements_cache[$file_path])) { - return $this->statements_cache[$file_path]; - } - - return null; + return $this->statements_cache[$file_path] ?? null; } /** @@ -81,11 +77,7 @@ public function saveStatementsToCache( public function loadExistingFileContentsFromCache(string $file_path): ?string { - if (isset($this->file_contents_cache[$file_path])) { - return $this->file_contents_cache[$file_path]; - } - - return null; + return $this->file_contents_cache[$file_path] ?? null; } public function cacheFileContents(string $file_path, string $file_contents): void diff --git a/src/Psalm/Internal/LanguageServer/Reference.php b/src/Psalm/Internal/LanguageServer/Reference.php index bedd931b589..fe376ef1d6b 100644 --- a/src/Psalm/Internal/LanguageServer/Reference.php +++ b/src/Psalm/Internal/LanguageServer/Reference.php @@ -11,14 +11,7 @@ */ final class Reference { - public string $file_path; - public string $symbol; - public Range $range; - - public function __construct(string $file_path, string $symbol, Range $range) + public function __construct(public string $file_path, public string $symbol, public Range $range) { - $this->file_path = $file_path; - $this->symbol = $symbol; - $this->range = $range; } } diff --git a/src/Psalm/Internal/LanguageServer/Server/TextDocument.php b/src/Psalm/Internal/LanguageServer/Server/TextDocument.php index 6081a651722..c51091ed976 100644 --- a/src/Psalm/Internal/LanguageServer/Server/TextDocument.php +++ b/src/Psalm/Internal/LanguageServer/Server/TextDocument.php @@ -38,20 +38,8 @@ */ final class TextDocument { - protected LanguageServer $server; - - protected Codebase $codebase; - - protected ProjectAnalyzer $project_analyzer; - - public function __construct( - LanguageServer $server, - Codebase $codebase, - ProjectAnalyzer $project_analyzer, - ) { - $this->server = $server; - $this->codebase = $codebase; - $this->project_analyzer = $project_analyzer; + public function __construct(protected LanguageServer $server, protected Codebase $codebase, protected ProjectAnalyzer $project_analyzer) + { } /** @@ -309,10 +297,7 @@ public function completion(TextDocumentIdentifier $textDocument, Position $posit } return new CompletionList($completion_items, false); } - } catch (UnanalyzedFileException $e) { - $this->server->logThrowable($e); - return null; - } catch (TypeParseTreeException $e) { + } catch (UnanalyzedFileException|TypeParseTreeException $e) { $this->server->logThrowable($e); return null; } @@ -323,10 +308,7 @@ public function completion(TextDocumentIdentifier $textDocument, Position $posit $completion_items = $this->codebase->getCompletionItemsForType($type_context); return new CompletionList($completion_items, false); } - } catch (UnexpectedValueException $e) { - $this->server->logThrowable($e); - return null; - } catch (TypeParseTreeException $e) { + } catch (UnexpectedValueException|TypeParseTreeException $e) { $this->server->logThrowable($e); return null; } diff --git a/src/Psalm/Internal/LanguageServer/Server/Workspace.php b/src/Psalm/Internal/LanguageServer/Server/Workspace.php index 2ce097eb0eb..d0f2fd01735 100644 --- a/src/Psalm/Internal/LanguageServer/Server/Workspace.php +++ b/src/Psalm/Internal/LanguageServer/Server/Workspace.php @@ -25,20 +25,8 @@ */ final class Workspace { - protected LanguageServer $server; - - protected Codebase $codebase; - - protected ProjectAnalyzer $project_analyzer; - - public function __construct( - LanguageServer $server, - Codebase $codebase, - ProjectAnalyzer $project_analyzer, - ) { - $this->server = $server; - $this->codebase = $codebase; - $this->project_analyzer = $project_analyzer; + public function __construct(protected LanguageServer $server, protected Codebase $codebase, protected ProjectAnalyzer $project_analyzer) + { } /** @@ -62,7 +50,7 @@ public function didChangeWatchedFiles(array $changes): void array_map(function (FileEvent $change) { try { return $this->server->uriToPath($change->uri); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return null; } }, $changes), diff --git a/src/Psalm/Internal/MethodIdentifier.php b/src/Psalm/Internal/MethodIdentifier.php index c41a4b8ba9e..fd4547e4580 100644 --- a/src/Psalm/Internal/MethodIdentifier.php +++ b/src/Psalm/Internal/MethodIdentifier.php @@ -6,32 +6,27 @@ use InvalidArgumentException; use Psalm\Storage\ImmutableNonCloneableTrait; +use Stringable; use function explode; use function is_string; use function ltrim; -use function strpos; +use function str_contains; use function strtolower; /** * @psalm-immutable * @internal */ -final class MethodIdentifier +final class MethodIdentifier implements Stringable { use ImmutableNonCloneableTrait; - public string $fq_class_name; - /** @var lowercase-string */ - public string $method_name; - /** * @param lowercase-string $method_name */ - public function __construct(string $fq_class_name, string $method_name) + public function __construct(public string $fq_class_name, public string $method_name) { - $this->fq_class_name = $fq_class_name; - $this->method_name = $method_name; } /** @@ -50,7 +45,7 @@ public static function wrap(string|MethodIdentifier $method_id): self */ public static function isValidMethodIdReference(string $method_id): bool { - return strpos($method_id, '::') !== false; + return str_contains($method_id, '::'); } /** diff --git a/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php b/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php index 609b098bdf2..a1ea12f334e 100644 --- a/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php @@ -22,11 +22,8 @@ final class AssignmentMapVisitor extends PhpParser\NodeVisitorAbstract */ protected array $assignment_map = []; - protected ?string $this_class_name = null; - - public function __construct(?string $this_class_name) + public function __construct(protected ?string $this_class_name) { - $this->this_class_name = $this_class_name; } public function enterNode(PhpParser\Node $node): ?int diff --git a/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php b/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php index c0c4d3e3f5a..3e86158ad38 100644 --- a/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php @@ -14,11 +14,8 @@ */ final class ConditionCloningVisitor extends NodeVisitorAbstract { - private NodeDataProvider $type_provider; - - public function __construct(NodeDataProvider $old_type_provider) + public function __construct(private readonly NodeDataProvider $type_provider) { - $this->type_provider = $old_type_provider; } /** diff --git a/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php b/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php index fc60185ab27..30fdc56e11f 100644 --- a/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php @@ -12,11 +12,8 @@ */ final class NodeCleanerVisitor extends PhpParser\NodeVisitorAbstract { - private NodeDataProvider $type_provider; - - public function __construct(NodeDataProvider $type_provider) + public function __construct(private readonly NodeDataProvider $type_provider) { - $this->type_provider = $type_provider; } public function enterNode(PhpParser\Node $node): ?int diff --git a/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php b/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php index 0a2d8c51e4b..02e5b977463 100644 --- a/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php @@ -13,21 +13,11 @@ */ final class OffsetShifterVisitor extends PhpParser\NodeVisitorAbstract { - private int $file_offset; - - private int $line_offset; - - /** @var array */ - private array $extra_offsets; - /** * @param array $extra_offsets */ - public function __construct(int $offset, int $line_offset, array $extra_offsets) + public function __construct(private readonly int $file_offset, private readonly int $line_offset, private array $extra_offsets) { - $this->file_offset = $offset; - $this->line_offset = $line_offset; - $this->extra_offsets = $extra_offsets; } public function enterNode(PhpParser\Node $node): ?int diff --git a/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php b/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php index d7cd254bed8..97366cb3128 100644 --- a/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php @@ -18,10 +18,6 @@ */ final class ParamReplacementVisitor extends PhpParser\NodeVisitorAbstract { - private string $old_name; - - private string $new_name; - /** @var list */ private array $replacements = []; @@ -29,10 +25,8 @@ final class ParamReplacementVisitor extends PhpParser\NodeVisitorAbstract private bool $new_new_name_used = false; - public function __construct(string $old_name, string $new_name) + public function __construct(private readonly string $old_name, private readonly string $new_name) { - $this->old_name = $old_name; - $this->new_name = $new_name; } public function enterNode(PhpParser\Node $node): ?int diff --git a/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php b/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php index 16176468c44..7a8ebe15cdb 100644 --- a/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php @@ -33,37 +33,21 @@ */ final class PartialParserVisitor extends PhpParser\NodeVisitorAbstract { - /** @var array */ - private array $offset_map; - private bool $must_rescan = false; - private int $non_method_changes; - - private string $a_file_contents; - - private string $b_file_contents; - - private int $a_file_contents_length; - - private Parser $parser; + private readonly int $non_method_changes; - private Collecting $error_handler; + private readonly int $a_file_contents_length; /** @param array $offset_map */ public function __construct( - Parser $parser, - Collecting $error_handler, - array $offset_map, - string $a_file_contents, - string $b_file_contents, + private readonly Parser $parser, + private readonly Collecting $error_handler, + private readonly array $offset_map, + private readonly string $a_file_contents, + private readonly string $b_file_contents, ) { - $this->parser = $parser; - $this->error_handler = $error_handler; - $this->offset_map = $offset_map; - $this->a_file_contents = $a_file_contents; $this->a_file_contents_length = strlen($a_file_contents); - $this->b_file_contents = $b_file_contents; $this->non_method_changes = count($offset_map); } diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php index 6e9f8715852..d073445d4e1 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php @@ -37,6 +37,7 @@ use function preg_replace; use function preg_split; use function reset; +use function str_contains; use function str_replace; use function strlen; use function strpos; @@ -454,7 +455,7 @@ public static function parse( $codebase->analysis_php_version_id, $has_errors, ); - } catch (Exception $e) { + } catch (Exception) { throw new DocblockParseException('Badly-formatted @method string ' . $method_entry); } @@ -593,7 +594,7 @@ private static function getMethodOffset(Doc $comment, string $method_entry): int $method_offset = 0; foreach ($lines as $i => $line) { - if (strpos($line, $method_entry) !== false) { + if (str_contains($line, $method_entry)) { $method_offset = $i; break; } diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php index 49958adcd0b..4086fd16f57 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php @@ -77,7 +77,6 @@ use function array_values; use function assert; use function count; -use function get_class; use function implode; use function preg_match; use function preg_replace; @@ -95,16 +94,10 @@ */ final class ClassLikeNodeScanner { - private FileScanner $file_scanner; - - private Codebase $codebase; - - private string $file_path; + private readonly string $file_path; private Config $config; - private FileStorage $file_storage; - /** * @var array */ @@ -115,10 +108,6 @@ final class ClassLikeNodeScanner */ public array $class_template_types = []; - private ?Name $namespace_name = null; - - private Aliases $aliases; - public ?ClassLikeStorage $storage = null; /** @@ -127,19 +116,14 @@ final class ClassLikeNodeScanner public array $type_aliases = []; public function __construct( - Codebase $codebase, - FileStorage $file_storage, - FileScanner $file_scanner, - Aliases $aliases, - ?Name $namespace_name, + private readonly Codebase $codebase, + private readonly FileStorage $file_storage, + private readonly FileScanner $file_scanner, + private Aliases $aliases, + private readonly ?Name $namespace_name, ) { - $this->codebase = $codebase; - $this->file_storage = $file_storage; - $this->file_scanner = $file_scanner; $this->file_path = $file_storage->file_path; - $this->aliases = $aliases; $this->config = Config::getInstance(); - $this->namespace_name = $namespace_name; } /** @@ -215,7 +199,7 @@ public function start(PhpParser\Node\Stmt\ClassLike $node): ?bool foreach ($storage->dependent_classlikes as $dependent_name_lc => $_) { try { $dependent_storage = $this->codebase->classlike_storage_provider->get($dependent_name_lc); - } catch (InvalidArgumentException $exception) { + } catch (InvalidArgumentException) { continue; } $dependent_storage->populated = false; @@ -504,7 +488,7 @@ public function start(PhpParser\Node\Stmt\ClassLike $node): ?bool ); $storage->yield = $yield_type; - } catch (TypeParseTreeException $e) { + } catch (TypeParseTreeException) { // do nothing } } @@ -868,7 +852,7 @@ public function finish(PhpParser\Node\Stmt\ClassLike $node): ClassLikeStorage '@psalm-type ' . $key . ' contains invalid reference: ' . $e->getMessage(), new CodeLocation($this->file_scanner, $node, null, true), ); - } catch (Exception $e) { + } catch (Exception) { $classlike_storage->docblock_issues[] = new InvalidDocblock( '@psalm-type ' . $key . ' contains invalid references', new CodeLocation($this->file_scanner, $node, null, true), @@ -1358,7 +1342,7 @@ private function visitClassConstDeclaration( && !( $const->value instanceof Concat && $inferred_type->isSingle() - && get_class($inferred_type->getSingleAtomic()) === TString::class + && $inferred_type->getSingleAtomic()::class === TString::class ) ) { $exists = true; diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php index 0255eef98c7..bfcfc996a89 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php @@ -390,7 +390,7 @@ public static function enterConditional( }); try { return (bool) $evaluator->evaluateSilently($expr); - } catch (ConstExprEvaluationException $e) { + } catch (ConstExprEvaluationException) { return null; } } diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php index bf5ac885de6..cecb0167e0b 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php @@ -29,7 +29,7 @@ use function explode; use function in_array; use function preg_match; -use function strpos; +use function str_contains; use function strtolower; use function substr; @@ -170,7 +170,7 @@ private static function registerClassMapFunctionCall( // only check the first @var comment break; } - } catch (DocblockParseException $e) { + } catch (DocblockParseException) { // do nothing } } @@ -215,7 +215,7 @@ private static function registerClassMapFunctionCall( } foreach ($mapping_function_ids as $potential_method_id) { - if (strpos($potential_method_id, '::') === false) { + if (!str_contains($potential_method_id, '::')) { continue; } diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php index 26ce42a0ac0..8d60023a4fc 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php @@ -29,10 +29,12 @@ use function preg_replace; use function preg_split; use function reset; +use function str_contains; +use function str_ends_with; use function str_replace; +use function str_starts_with; use function stripos; use function strlen; -use function strpos; use function strtolower; use function substr; use function substr_count; @@ -263,7 +265,7 @@ public static function parse( if (count($param_parts) === 2) { $taint_type = $param_parts[1]; - if (strpos($taint_type, 'exec_') === 0) { + if (str_starts_with($taint_type, 'exec_')) { $taint_type = substr($taint_type, 5); if ($taint_type === 'tainted') { @@ -578,7 +580,7 @@ public static function parse( */ private static function sanitizeAssertionLineParts(array $line_parts): array { - if (count($line_parts) < 2 || strpos($line_parts[1], '$') === false) { + if (count($line_parts) < 2 || !str_contains($line_parts[1], '$')) { throw new IncorrectDocblockException('Misplaced variable'); } @@ -588,7 +590,7 @@ private static function sanitizeAssertionLineParts(array $line_parts): array $param_name_parts = explode('->', $line_parts[1]); foreach ($param_name_parts as $i => $param_name_part) { - if (substr($param_name_part, -2) === '()') { + if (str_ends_with($param_name_part, '()')) { $param_name_parts[$i] = strtolower($param_name_part); } } diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php index 0d9bc183cba..c4c9060e114 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php @@ -60,9 +60,11 @@ use function preg_match; use function preg_replace; use function preg_split; +use function str_contains; +use function str_ends_with; use function str_replace; +use function str_starts_with; use function strlen; -use function strpos; use function strtolower; use function substr; use function substr_replace; @@ -471,9 +473,7 @@ private static function getConditionalSanitizedTypeTokens( = $storage->template_types[$template_name]; $param_type_mapping[$token_body] = $template_name; } else { - $template_as_type = $param_storage->type - ? $param_storage->type - : Type::getMixed(); + $template_as_type = $param_storage->type ?: Type::getMixed(); $storage->template_types[$template_name] = [ $template_function_id => $template_as_type, @@ -721,7 +721,7 @@ private static function improveParamsFromDocblock( $param_name = $docblock_param['name']; $docblock_param_variadic = false; - if (strpos($param_name, '...') === 0) { + if (str_starts_with($param_name, '...')) { $docblock_param_variadic = true; $param_name = substr($param_name, 3); } @@ -1095,7 +1095,7 @@ private static function handleTaintFlow( if (isset($flow_parts[1]) && trim($flow_parts[1]) === 'return') { $source_param_string = trim($flow_parts[0]); - if ($source_param_string[0] === '(' && substr($source_param_string, -1) === ')') { + if ($source_param_string[0] === '(' && str_ends_with($source_param_string, ')')) { $source_params = preg_split('/, ?/', substr($source_param_string, 1, -1)); if ($source_params === false) { throw new AssertionError(preg_last_error_msg()); @@ -1113,7 +1113,7 @@ private static function handleTaintFlow( } } - if (isset($flow_parts[0]) && strpos(trim($flow_parts[0]), 'proxy') === 0) { + if (isset($flow_parts[0]) && str_starts_with(trim($flow_parts[0]), 'proxy')) { $proxy_call = trim(substr($flow_parts[0], strlen('proxy'))); [$fully_qualified_name, $source_param_string] = explode('(', $proxy_call, 2); @@ -1250,7 +1250,7 @@ private static function handleAssertions( continue 2; } - if (strpos($assertion['param_name'], $param->name.'->') === 0) { + if (str_starts_with($assertion['param_name'], $param->name.'->')) { $storage->assertions[] = new Possibilities( substr_replace($assertion['param_name'], (string) $i, 0, strlen($param->name)), $assertion_type_parts, @@ -1260,7 +1260,7 @@ private static function handleAssertions( } $storage->assertions[] = new Possibilities( - (strpos($assertion['param_name'], '$') === false ? '$' : '') . $assertion['param_name'], + (!str_contains($assertion['param_name'], '$') ? '$' : '') . $assertion['param_name'], $assertion_type_parts, ); } @@ -1297,7 +1297,7 @@ private static function handleAssertions( continue 2; } - if (strpos($assertion['param_name'], $param->name.'->') === 0) { + if (str_starts_with($assertion['param_name'], $param->name.'->')) { $storage->if_true_assertions[] = new Possibilities( str_replace($param->name, (string) $i, $assertion['param_name']), $assertion_type_parts, @@ -1307,7 +1307,7 @@ private static function handleAssertions( } $storage->if_true_assertions[] = new Possibilities( - (strpos($assertion['param_name'], '$') === false ? '$' : '') . $assertion['param_name'], + (!str_contains($assertion['param_name'], '$') ? '$' : '') . $assertion['param_name'], $assertion_type_parts, ); } @@ -1344,7 +1344,7 @@ private static function handleAssertions( continue 2; } - if (strpos($assertion['param_name'], $param->name.'->') === 0) { + if (str_starts_with($assertion['param_name'], $param->name.'->')) { $storage->if_false_assertions[] = new Possibilities( str_replace($param->name, (string) $i, $assertion['param_name']), $assertion_type_parts, @@ -1354,7 +1354,7 @@ private static function handleAssertions( } $storage->if_false_assertions[] = new Possibilities( - (strpos($assertion['param_name'], '$') === false ? '$' : '') . $assertion['param_name'], + (!str_contains($assertion['param_name'], '$') ? '$' : '') . $assertion['param_name'], $assertion_type_parts, ); } diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php index b2bc3a4f6af..9b769b5700a 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php @@ -62,7 +62,8 @@ use function in_array; use function is_string; use function spl_object_id; -use function strpos; +use function str_contains; +use function str_starts_with; use function strtolower; /** @@ -70,29 +71,9 @@ */ final class FunctionLikeNodeScanner { - private FileScanner $file_scanner; + private readonly string $file_path; - private Codebase $codebase; - - private string $file_path; - - private Config $config; - - private FileStorage $file_storage; - - private ?ClassLikeStorage $classlike_storage = null; - - /** - * @var array> - */ - private array $existing_function_template_types; - - private Aliases $aliases; - - /** - * @var array - */ - private array $type_aliases; + private readonly Config $config; public ?FunctionLikeStorage $storage = null; @@ -101,23 +82,16 @@ final class FunctionLikeNodeScanner * @param array $type_aliases */ public function __construct( - Codebase $codebase, - FileScanner $file_scanner, - FileStorage $file_storage, - Aliases $aliases, - array $type_aliases, - ?ClassLikeStorage $classlike_storage, - array $existing_function_template_types, + private readonly Codebase $codebase, + private readonly FileScanner $file_scanner, + private readonly FileStorage $file_storage, + private readonly Aliases $aliases, + private readonly array $type_aliases, + private ?ClassLikeStorage $classlike_storage, + private readonly array $existing_function_template_types, ) { - $this->codebase = $codebase; - $this->file_storage = $file_storage; - $this->file_scanner = $file_scanner; $this->file_path = $file_storage->file_path; - $this->aliases = $aliases; - $this->type_aliases = $type_aliases; $this->config = Config::getInstance(); - $this->classlike_storage = $classlike_storage; - $this->existing_function_template_types = $existing_function_template_types; } /** @@ -271,7 +245,7 @@ public function start( $classlike_storage->properties[$property_name]->getter_method = strtolower($stmt->name->name); } - } elseif (strpos($stmt->name->name, 'assert') === 0 + } elseif (str_starts_with($stmt->name->name, 'assert') && $stmt->stmts ) { $var_assertions = []; @@ -303,7 +277,7 @@ public function start( try { $negated_formula = Algebra::negateFormula($if_clauses); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $var_assertions = []; break; } @@ -329,7 +303,7 @@ public function start( $param_offset, $rule_part, ); - } elseif (strpos($var_id, '$this->') === 0) { + } elseif (str_starts_with($var_id, '$this->')) { $var_assertions[] = new Possibilities( $var_id, $rule_part, @@ -1044,7 +1018,7 @@ private function createStorageForFunctionLike( $code_location, $cased_function_id, ); - } catch (IncorrectDocblockException|DocblockParseException $e) { + } catch (IncorrectDocblockException|DocblockParseException) { } if ($docblock_info) { if ($docblock_info->since_php_major_version && !$this->aliases->namespace) { @@ -1079,7 +1053,7 @@ private function createStorageForFunctionLike( if ($method_name_lc === strtolower($class_name) && !isset($classlike_storage->methods['__construct']) - && strpos($fq_classlike_name, '\\') === false + && !str_contains($fq_classlike_name, '\\') && $this->codebase->analysis_php_version_id <= 7_04_00 ) { $this->codebase->methods->setDeclaringMethodId( diff --git a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php index 3ff897b4e5d..fd95f55faf0 100644 --- a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php @@ -36,11 +36,9 @@ use Psalm\Type; use UnexpectedValueException; -use function array_merge; use function array_pop; use function end; use function explode; -use function get_class; use function in_array; use function is_string; use function reset; @@ -57,15 +55,9 @@ final class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements Fi { private Aliases $aliases; - private FileScanner $file_scanner; - - private Codebase $codebase; - private string $file_path; - private bool $scan_deep; - - private FileStorage $file_storage; + private readonly bool $scan_deep; /** * @var array @@ -92,18 +84,15 @@ final class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements Fi * @var array */ private array $bad_classes = []; - private EventDispatcher $eventDispatcher; + private readonly EventDispatcher $eventDispatcher; public function __construct( - Codebase $codebase, - FileScanner $file_scanner, - FileStorage $file_storage, + private readonly Codebase $codebase, + private readonly FileScanner $file_scanner, + private readonly FileStorage $file_storage, ) { - $this->codebase = $codebase; - $this->file_scanner = $file_scanner; $this->file_path = $file_scanner->file_path; $this->scan_deep = $file_scanner->will_analyze; - $this->file_storage = $file_storage; $this->aliases = $this->file_storage->aliases = new Aliases(); $this->eventDispatcher = $this->codebase->config->eventDispatcher; } @@ -161,7 +150,7 @@ public function enterNode(PhpParser\Node $node): ?int return PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN; } - $this->type_aliases = array_merge($this->type_aliases, $classlike_node_scanner->type_aliases); + $this->type_aliases = [...$this->type_aliases, ...$classlike_node_scanner->type_aliases]; } elseif ($node instanceof PhpParser\Node\Stmt\TryCatch) { foreach ($node->catches as $catch) { foreach ($catch->types as $catch_type) { @@ -351,7 +340,7 @@ public function enterNode(PhpParser\Node $node): ?int $template_types, $this->type_aliases, ); - } catch (DocblockParseException $e) { + } catch (DocblockParseException) { // do nothing } @@ -562,7 +551,7 @@ public function leaveNode(PhpParser\Node $node) ) { $e = reset($functionlike_node_scanner->storage->docblock_issues); - $fqcn_parts = explode('\\', get_class($e)); + $fqcn_parts = explode('\\', $e::class); $issue_type = array_pop($fqcn_parts); $message = $e instanceof TaintedInput diff --git a/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php b/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php index 3b13e077bac..e62040ae3e9 100644 --- a/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php +++ b/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php @@ -21,7 +21,7 @@ */ final class SimpleNameResolver extends NodeVisitorAbstract { - private NameContext $nameContext; + private readonly NameContext $nameContext; private ?int $start_change = null; diff --git a/src/Psalm/Internal/PhpVisitor/TraitFinder.php b/src/Psalm/Internal/PhpVisitor/TraitFinder.php index a79f8a5e21b..ef0f2e3b600 100644 --- a/src/Psalm/Internal/PhpVisitor/TraitFinder.php +++ b/src/Psalm/Internal/PhpVisitor/TraitFinder.php @@ -24,11 +24,8 @@ final class TraitFinder extends PhpParser\NodeVisitorAbstract /** @var list */ private array $matching_trait_nodes = []; - private string $fq_trait_name; - - public function __construct(string $fq_trait_name) + public function __construct(private readonly string $fq_trait_name) { - $this->fq_trait_name = $fq_trait_name; } public function enterNode(PhpParser\Node $node, bool &$traverseChildren = true): ?int @@ -73,7 +70,7 @@ public function getNode(): ?PhpParser\Node\Stmt\Trait_ try { $reflection_trait = new ReflectionClass($this->fq_trait_name); - } catch (Throwable $t) { + } catch (Throwable) { return null; } diff --git a/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php b/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php index 1236d8c0b47..9f5c45cbab9 100644 --- a/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php @@ -13,15 +13,8 @@ */ final class TypeMappingVisitor extends NodeVisitorAbstract { - private NodeDataProvider $fake_type_provider; - private NodeDataProvider $real_type_provider; - - public function __construct( - NodeDataProvider $fake_type_provider, - NodeDataProvider $real_type_provider, - ) { - $this->fake_type_provider = $fake_type_provider; - $this->real_type_provider = $real_type_provider; + public function __construct(private readonly NodeDataProvider $fake_type_provider, private readonly NodeDataProvider $real_type_provider) + { } /** diff --git a/src/Psalm/Internal/PhpVisitor/YieldTypeCollector.php b/src/Psalm/Internal/PhpVisitor/YieldTypeCollector.php index ddb1360bd92..ed41640f4cb 100644 --- a/src/Psalm/Internal/PhpVisitor/YieldTypeCollector.php +++ b/src/Psalm/Internal/PhpVisitor/YieldTypeCollector.php @@ -23,11 +23,8 @@ final class YieldTypeCollector extends NodeVisitorAbstract /** @var list */ private array $yield_types = []; - private NodeDataProvider $nodes; - - public function __construct(NodeDataProvider $nodes) + public function __construct(private readonly NodeDataProvider $nodes) { - $this->nodes = $nodes; } public function enterNode(Node $node): ?int @@ -45,7 +42,7 @@ public function enterNode(Node $node): ?int $generator_type = new TGenericObject( 'Generator', [ - $key_type ? $key_type : Type::getInt(), + $key_type ?: Type::getInt(), $value_type, Type::getMixed(), Type::getMixed(), diff --git a/src/Psalm/Internal/PluginManager/Command/DisableCommand.php b/src/Psalm/Internal/PluginManager/Command/DisableCommand.php index 9104dbaa904..aa174a85c62 100644 --- a/src/Psalm/Internal/PluginManager/Command/DisableCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/DisableCommand.php @@ -25,11 +25,8 @@ */ final class DisableCommand extends Command { - private PluginListFactory $plugin_list_factory; - - public function __construct(PluginListFactory $plugin_list_factory) + public function __construct(private readonly PluginListFactory $plugin_list_factory) { - $this->plugin_list_factory = $plugin_list_factory; parent::__construct(); } @@ -67,7 +64,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { $plugin_class = $plugin_list->resolvePluginClass($plugin_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { $io->error('Unknown plugin class ' . $plugin_name); return 2; diff --git a/src/Psalm/Internal/PluginManager/Command/EnableCommand.php b/src/Psalm/Internal/PluginManager/Command/EnableCommand.php index 6a48504ddcb..858fe750852 100644 --- a/src/Psalm/Internal/PluginManager/Command/EnableCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/EnableCommand.php @@ -25,11 +25,8 @@ */ final class EnableCommand extends Command { - private PluginListFactory $plugin_list_factory; - - public function __construct(PluginListFactory $plugin_list_factory) + public function __construct(private readonly PluginListFactory $plugin_list_factory) { - $this->plugin_list_factory = $plugin_list_factory; parent::__construct(); } @@ -67,7 +64,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { $plugin_class = $plugin_list->resolvePluginClass($plugin_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { $io->error('Unknown plugin class ' . $plugin_name); return 2; diff --git a/src/Psalm/Internal/PluginManager/Command/ShowCommand.php b/src/Psalm/Internal/PluginManager/Command/ShowCommand.php index 77a8499ec8e..fdc782562e4 100644 --- a/src/Psalm/Internal/PluginManager/Command/ShowCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/ShowCommand.php @@ -26,11 +26,8 @@ */ final class ShowCommand extends Command { - private PluginListFactory $plugin_list_factory; - - public function __construct(PluginListFactory $plugin_list_factory) + public function __construct(private readonly PluginListFactory $plugin_list_factory) { - $this->plugin_list_factory = $plugin_list_factory; parent::__construct(); } diff --git a/src/Psalm/Internal/PluginManager/ComposerLock.php b/src/Psalm/Internal/PluginManager/ComposerLock.php index 03c9733d95c..bb361a15f06 100644 --- a/src/Psalm/Internal/PluginManager/ComposerLock.php +++ b/src/Psalm/Internal/PluginManager/ComposerLock.php @@ -20,13 +20,9 @@ */ final class ComposerLock { - /** @var string[] */ - private array $file_names; - /** @param string[] $file_names */ - public function __construct(array $file_names) + public function __construct(private readonly array $file_names) { - $this->file_names = $file_names; } /** diff --git a/src/Psalm/Internal/PluginManager/ConfigFile.php b/src/Psalm/Internal/PluginManager/ConfigFile.php index 0f94cd85825..7ffb2f9084b 100644 --- a/src/Psalm/Internal/PluginManager/ConfigFile.php +++ b/src/Psalm/Internal/PluginManager/ConfigFile.php @@ -23,16 +23,12 @@ final class ConfigFile { private string $path; - private string $current_dir; - private ?string $psalm_header = null; private ?int $psalm_tag_end_pos = null; - public function __construct(string $current_dir, ?string $explicit_path) + public function __construct(private readonly string $current_dir, ?string $explicit_path) { - $this->current_dir = $current_dir; - if ($explicit_path) { $this->path = $explicit_path; } else { diff --git a/src/Psalm/Internal/PluginManager/PluginList.php b/src/Psalm/Internal/PluginManager/PluginList.php index eee2faddf8a..89c41e7be3a 100644 --- a/src/Psalm/Internal/PluginManager/PluginList.php +++ b/src/Psalm/Internal/PluginManager/PluginList.php @@ -11,27 +11,21 @@ use function array_flip; use function array_key_exists; use function array_search; -use function strpos; +use function str_contains; /** * @internal */ class PluginList { - private ?ConfigFile $config_file = null; - - private ComposerLock $composer_lock; - /** @var ?array [pluginClass => packageName] */ private ?array $all_plugins = null; /** @var ?array [pluginClass => ?packageName] */ private ?array $enabled_plugins = null; - public function __construct(?ConfigFile $config_file, ComposerLock $composer_lock) + public function __construct(private readonly ?ConfigFile $config_file, private readonly ComposerLock $composer_lock) { - $this->config_file = $config_file; - $this->composer_lock = $composer_lock; } /** @@ -74,7 +68,7 @@ public function getAll(): array public function resolvePluginClass(string $class_or_package): string { - if (false === strpos($class_or_package, '/')) { + if (!str_contains($class_or_package, '/')) { return $class_or_package; // must be a class then } diff --git a/src/Psalm/Internal/PluginManager/PluginListFactory.php b/src/Psalm/Internal/PluginManager/PluginListFactory.php index fafbc267532..c6daf1b634b 100644 --- a/src/Psalm/Internal/PluginManager/PluginListFactory.php +++ b/src/Psalm/Internal/PluginManager/PluginListFactory.php @@ -20,21 +20,15 @@ */ class PluginListFactory { - private string $project_root; - - private string $psalm_root; - - public function __construct(string $project_root, string $psalm_root) + public function __construct(private readonly string $project_root, private readonly string $psalm_root) { - $this->project_root = $project_root; - $this->psalm_root = $psalm_root; } public function __invoke(string $current_dir, ?string $config_file_path = null): PluginList { try { $config_file = new ConfigFile($current_dir, $config_file_path); - } catch (RuntimeException $exception) { + } catch (RuntimeException) { $config_file = null; } $composer_lock = new ComposerLock($this->findLockFiles()); diff --git a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php index 09db0b64f96..c35c5e38238 100644 --- a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php @@ -14,7 +14,6 @@ use function dirname; use function file_exists; use function filemtime; -use function get_class; use function hash; use function is_dir; use function is_null; @@ -29,7 +28,7 @@ */ class ClassLikeStorageCacheProvider { - private Cache $cache; + private readonly Cache $cache; private string $modified_timestamps = ''; @@ -93,7 +92,7 @@ public function getLatestFromCache( $cache_hash = $this->getCacheHash($file_path, $file_contents); /** @psalm-suppress TypeDoesNotContainType */ - if (@get_class($cached_value) === '__PHP_Incomplete_Class' + if (@$cached_value::class === '__PHP_Incomplete_Class' || $cache_hash !== $cached_value->hash ) { $this->cache->deleteItem($this->getCacheLocationForClass($fq_classlike_name_lc, $file_path)); @@ -106,7 +105,7 @@ public function getLatestFromCache( private function getCacheHash(?string $_unused_file_path, ?string $file_contents): string { - $data = $file_contents ? $file_contents : $this->modified_timestamps; + $data = $file_contents ?: $this->modified_timestamps; return PHP_VERSION_ID >= 8_01_00 ? hash('xxh128', $data) : hash('md4', $data); } diff --git a/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php b/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php index 8260b207d18..1be26f84398 100644 --- a/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php +++ b/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php @@ -8,7 +8,6 @@ use LogicException; use Psalm\Storage\ClassLikeStorage; -use function array_merge; use function strtolower; /** @@ -28,11 +27,8 @@ final class ClassLikeStorageProvider */ private static array $new_storage = []; - public ?ClassLikeStorageCacheProvider $cache = null; - - public function __construct(?ClassLikeStorageCacheProvider $cache = null) + public function __construct(public ?ClassLikeStorageCacheProvider $cache = null) { - $this->cache = $cache; } /** @@ -103,8 +99,8 @@ public function getNew(): array */ public function addMore(array $more): void { - self::$new_storage = array_merge(self::$new_storage, $more); - self::$storage = array_merge(self::$storage, $more); + self::$new_storage = [...self::$new_storage, ...$more]; + self::$storage = [...self::$storage, ...$more]; } public function makeNew(string $fq_classlike_name_lc): void diff --git a/src/Psalm/Internal/Provider/FakeFileProvider.php b/src/Psalm/Internal/Provider/FakeFileProvider.php index a5e18fd7bb8..134243213b7 100644 --- a/src/Psalm/Internal/Provider/FakeFileProvider.php +++ b/src/Psalm/Internal/Provider/FakeFileProvider.php @@ -5,7 +5,7 @@ namespace Psalm\Internal\Provider; use function microtime; -use function strpos; +use function str_starts_with; /** * @internal @@ -86,7 +86,7 @@ public function getFilesInDir(string $dir_path, array $file_extensions, callable $file_paths = parent::getFilesInDir($dir_path, $file_extensions, $filter); foreach ($this->fake_files as $file_path => $_) { - if (strpos($file_path, $dir_path) === 0) { + if (str_starts_with($file_path, $dir_path)) { $file_paths[] = $file_path; } } diff --git a/src/Psalm/Internal/Provider/FileProvider.php b/src/Psalm/Internal/Provider/FileProvider.php index b070f7f3625..2f26b8e32b7 100644 --- a/src/Psalm/Internal/Provider/FileProvider.php +++ b/src/Psalm/Internal/Provider/FileProvider.php @@ -170,7 +170,7 @@ public function getFilesInDir(string $dir_path, array $file_extensions, callable $iterator = new RecursiveCallbackFilterIterator( $iterator, /** @param mixed $_ */ - static function (string $current, $_, RecursiveIterator $iterator) use ($filter): bool { + static function (string $current, mixed $_, RecursiveIterator $iterator) use ($filter): bool { if ($iterator->hasChildren()) { $path = $current . DIRECTORY_SEPARATOR; } else { diff --git a/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php b/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php index e91df5dde67..793e916989a 100644 --- a/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php @@ -50,13 +50,10 @@ class FileReferenceCacheProvider private const FILE_MISSING_MEMBER_CACHE_NAME = 'file_missing_member'; private const UNKNOWN_MEMBER_CACHE_NAME = 'unknown_member_references'; private const METHOD_PARAM_USE_CACHE_NAME = 'method_param_uses'; - - protected Config $config; protected Cache $cache; - public function __construct(Config $config) + public function __construct(protected Config $config) { - $this->config = $config; $this->cache = new Cache($config); } diff --git a/src/Psalm/Internal/Provider/FileReferenceProvider.php b/src/Psalm/Internal/Provider/FileReferenceProvider.php index 0e74f56e687..22d39dc4876 100644 --- a/src/Psalm/Internal/Provider/FileReferenceProvider.php +++ b/src/Psalm/Internal/Provider/FileReferenceProvider.php @@ -165,13 +165,8 @@ final class FileReferenceProvider */ private static array $method_param_uses = []; - private FileProvider $file_provider; - public ?FileReferenceCacheProvider $cache = null; - - public function __construct(FileProvider $file_provider, ?FileReferenceCacheProvider $cache = null) + public function __construct(private readonly FileProvider $file_provider, public ?FileReferenceCacheProvider $cache = null) { - $this->file_provider = $file_provider; - $this->cache = $cache; } /** @@ -386,7 +381,7 @@ private function calculateFilesReferencingFile(Codebase $codebase, string $file) try { $referenced_files[] = $codebase->scanner->getClassLikeFilePath($fq_class_name_lc); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { if (isset(self::$classlike_files[$fq_class_name_lc])) { $referenced_files[] = self::$classlike_files[$fq_class_name_lc]; } @@ -1233,7 +1228,7 @@ public function getTypeCoverage(): array */ public function setTypeCoverage(array $mixed_counts): void { - self::$mixed_counts = array_merge(self::$mixed_counts, $mixed_counts); + self::$mixed_counts = [...self::$mixed_counts, ...$mixed_counts]; } /** diff --git a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php index e062ff7d117..8419afd80fb 100644 --- a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php @@ -14,7 +14,6 @@ use function dirname; use function file_exists; use function filemtime; -use function get_class; use function hash; use function is_dir; use function mkdir; @@ -30,7 +29,7 @@ class FileStorageCacheProvider { private string $modified_timestamps = ''; - private Cache $cache; + private readonly Cache $cache; private const FILE_STORAGE_CACHE_DIRECTORY = 'file_cache'; @@ -92,7 +91,7 @@ public function getLatestFromCache(string $file_path, string $file_contents): ?F $cache_hash = $this->getCacheHash($file_path, $file_contents); /** @psalm-suppress TypeDoesNotContainType */ - if (@get_class($cached_value) === '__PHP_Incomplete_Class' + if (@$cached_value::class === '__PHP_Incomplete_Class' || $cache_hash !== $cached_value->hash ) { $this->removeCacheForFile($file_path); @@ -113,7 +112,7 @@ private function getCacheHash(string $_unused_file_path, string $file_contents): // do not concatenate, as $file_contents can be big and performance will be bad // the timestamp is only needed if we don't have file contents // as same contents should give same results, independent of when file was modified - $data = $file_contents ? $file_contents : $this->modified_timestamps; + $data = $file_contents ?: $this->modified_timestamps; return PHP_VERSION_ID >= 8_01_00 ? hash('xxh128', $data) : hash('md4', $data); } diff --git a/src/Psalm/Internal/Provider/FileStorageProvider.php b/src/Psalm/Internal/Provider/FileStorageProvider.php index 059f6d7fabd..747a11e6d60 100644 --- a/src/Psalm/Internal/Provider/FileStorageProvider.php +++ b/src/Psalm/Internal/Provider/FileStorageProvider.php @@ -7,7 +7,6 @@ use InvalidArgumentException; use Psalm\Storage\FileStorage; -use function array_merge; use function strtolower; /** @@ -31,11 +30,8 @@ final class FileStorageProvider */ private static array $new_storage = []; - public ?FileStorageCacheProvider $cache = null; - - public function __construct(?FileStorageCacheProvider $cache = null) + public function __construct(public ?FileStorageCacheProvider $cache = null) { - $this->cache = $cache; } public function get(string $file_path): FileStorage @@ -103,8 +99,8 @@ public function getNew(): array */ public function addMore(array $more): void { - self::$new_storage = array_merge(self::$new_storage, $more); - self::$storage = array_merge(self::$storage, $more); + self::$new_storage = [...self::$new_storage, ...$more]; + self::$storage = [...self::$storage, ...$more]; } public function create(string $file_path): FileStorage diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index 739fc54d852..6c74fc06b22 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -44,7 +44,7 @@ class ParserCacheProvider private const PARSER_CACHE_DIRECTORY = 'php-parser'; private const FILE_CONTENTS_CACHE_DIRECTORY = 'file-caches'; - private Cache $cache; + private readonly Cache $cache; /** * A map of filename hashes to contents hashes @@ -60,12 +60,9 @@ class ParserCacheProvider */ protected array $new_file_content_hashes = []; - private bool $use_file_cache; - - public function __construct(Config $config, bool $use_file_cache = true) + public function __construct(Config $config, private readonly bool $use_file_cache = true) { $this->cache = new Cache($config); - $this->use_file_cache = $use_file_cache; } /** @@ -202,7 +199,7 @@ private function getExistingFileContentHashes(): array } /** @psalm-suppress MixedAssignment */ - $hashes_decoded = json_decode($hashes_encoded, true); + $hashes_decoded = json_decode($hashes_encoded, true, 512, JSON_THROW_ON_ERROR); if (!is_array($hashes_decoded)) { throw new UnexpectedValueException( diff --git a/src/Psalm/Internal/Provider/ProjectCacheProvider.php b/src/Psalm/Internal/Provider/ProjectCacheProvider.php index 8bfe3c41e24..125e6f9c725 100644 --- a/src/Psalm/Internal/Provider/ProjectCacheProvider.php +++ b/src/Psalm/Internal/Provider/ProjectCacheProvider.php @@ -31,11 +31,8 @@ class ProjectCacheProvider private ?string $composer_lock_hash = null; - private string $composer_lock_location; - - public function __construct(string $composer_lock_location) + public function __construct(private readonly string $composer_lock_location) { - $this->composer_lock_location = $composer_lock_location; } public function canDiffFiles(): bool diff --git a/src/Psalm/Internal/Provider/Providers.php b/src/Psalm/Internal/Provider/Providers.php index 673a6ab2e2b..e6d5707dfd7 100644 --- a/src/Psalm/Internal/Provider/Providers.php +++ b/src/Psalm/Internal/Provider/Providers.php @@ -20,10 +20,6 @@ */ final class Providers { - public FileProvider $file_provider; - - public ?ParserCacheProvider $parser_cache_provider = null; - public FileStorageProvider $file_storage_provider; public ClassLikeStorageProvider $classlike_storage_provider; @@ -32,20 +28,14 @@ final class Providers public FileReferenceProvider $file_reference_provider; - public ?ProjectCacheProvider $project_cache_provider = null; - public function __construct( - FileProvider $file_provider, - ?ParserCacheProvider $parser_cache_provider = null, + public FileProvider $file_provider, + public ?ParserCacheProvider $parser_cache_provider = null, ?FileStorageCacheProvider $file_storage_cache_provider = null, ?ClassLikeStorageCacheProvider $classlike_storage_cache_provider = null, ?FileReferenceCacheProvider $file_reference_cache_provider = null, - ?ProjectCacheProvider $project_cache_provider = null, + public ?ProjectCacheProvider $project_cache_provider = null, ) { - $this->file_provider = $file_provider; - $this->parser_cache_provider = $parser_cache_provider; - $this->project_cache_provider = $project_cache_provider; - $this->file_storage_provider = new FileStorageProvider($file_storage_cache_provider); $this->classlike_storage_provider = new ClassLikeStorageProvider($classlike_storage_cache_provider); $this->statements_provider = new StatementsProvider( diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php index f8230115991..69cb75a24ed 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php @@ -39,7 +39,7 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev $second_arg_type = isset($call_args[1]) ? $statements_source->node_data->getType($call_args[1]->value) : null; $third_arg_type = isset($call_args[2]) ? $statements_source->node_data->getType($call_args[2]->value) : null; - $value_type_from_third_arg = $third_arg_type ? $third_arg_type : Type::getMixed(); + $value_type_from_third_arg = $third_arg_type ?: Type::getMixed(); if ($first_arg_type && $second_arg_type && $third_arg_type && $first_arg_type->isSingleIntLiteral() diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFilterReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFilterReturnTypeProvider.php index 2d1734a0d7d..b23c16d1266 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFilterReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFilterReturnTypeProvider.php @@ -270,7 +270,7 @@ static function ($keyed_type) use ($statements_source, $context) { $statements_source, $codebase, ); - } catch (ComplicatedExpressionException $e) { + } catch (ComplicatedExpressionException) { $filter_clauses = []; } diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php index a6ae833b414..50f98b3af74 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php @@ -44,7 +44,7 @@ use function in_array; use function mt_rand; use function reset; -use function strpos; +use function str_contains; use function substr; /** @@ -417,7 +417,7 @@ public static function getReturnTypeFromMappingIds( ); } - if (strpos($mapping_function_id_part, '::') !== false) { + if (str_contains($mapping_function_id_part, '::')) { $is_instance = false; if ($mapping_function_id_part[0] === '$') { @@ -527,7 +527,7 @@ public static function getReturnTypeFromMappingIds( public static function cleanContext(Context $context, int $fake_var_discriminator): void { foreach ($context->vars_in_scope as $var_in_scope => $_) { - if (strpos($var_in_scope, "__fake_{$fake_var_discriminator}_") !== false) { + if (str_contains($var_in_scope, "__fake_{$fake_var_discriminator}_")) { unset($context->vars_in_scope[$var_in_scope]); } } diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPointerAdjustmentReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPointerAdjustmentReturnTypeProvider.php index 5a62a189743..42e146c36cc 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPointerAdjustmentReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPointerAdjustmentReturnTypeProvider.php @@ -29,7 +29,7 @@ final class ArrayPointerAdjustmentReturnTypeProvider implements FunctionReturnTy /** * These functions are already handled by the CoreGenericFunctions stub */ - const IGNORE_FUNCTION_IDS_FOR_FALSE_RETURN_TYPE = [ + public const IGNORE_FUNCTION_IDS_FOR_FALSE_RETURN_TYPE = [ 'reset', 'end', 'current', diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.php index c316e7debb1..cd29cf75535 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.php @@ -25,7 +25,7 @@ use function explode; use function in_array; use function reset; -use function strpos; +use function str_contains; use function strtolower; use function substr; @@ -218,7 +218,7 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev $part_match_found = true; } } elseif ($mapping_function_id_part) { - if (strpos($mapping_function_id_part, '::') !== false) { + if (str_contains($mapping_function_id_part, '::')) { if ($mapping_function_id_part[0] === '$') { $mapping_function_id_part = substr($mapping_function_id_part, 1); } diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/MinMaxReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/MinMaxReturnTypeProvider.php index db7000bc721..cd9f841bcb1 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/MinMaxReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/MinMaxReturnTypeProvider.php @@ -19,7 +19,6 @@ use function array_filter; use function assert; use function count; -use function get_class; use function in_array; use function max; use function min; @@ -89,7 +88,7 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev } elseif ($atomic_type instanceof TIntRange) { $min_bounds[] = $atomic_type->min_bound; $max_bounds[] = $atomic_type->max_bound; - } elseif (get_class($atomic_type) === TInt::class) { + } elseif ($atomic_type::class === TInt::class) { $min_bounds[] = null; $max_bounds[] = null; } else { diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php index 5e95fdb824f..60cc7bca87b 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php @@ -62,104 +62,81 @@ private static function handleFetch(MethodReturnTypeProviderEvent $event): ?Unio break; } } - - switch ($fetch_mode) { - case 2: // PDO::FETCH_ASSOC - array|false - return new Union([ - new TArray([ - Type::getString(), - new Union([ - new TScalar(), - new TNull(), - ]), + return match ($fetch_mode) { + 2 => new Union([ + new TArray([ + Type::getString(), + new Union([ + new TScalar(), + new TNull(), ]), - new TFalse(), - ]); - - case 4: // PDO::FETCH_BOTH - array|false - return new Union([ - new TArray([ - Type::getArrayKey(), - new Union([ - new TScalar(), - new TNull(), - ]), + ]), + new TFalse(), + ]), + 4 => new Union([ + new TArray([ + Type::getArrayKey(), + new Union([ + new TScalar(), + new TNull(), ]), - new TFalse(), - ]); - - case 6: // PDO::FETCH_BOUND - bool - return Type::getBool(); - - case 7: // PDO::FETCH_COLUMN - scalar|null|false - return new Union([ - new TScalar(), - new TNull(), - new TFalse(), - ]); - - case 8: // PDO::FETCH_CLASS - object|false - return new Union([ - new TObject(), - new TFalse(), - ]); - - case 1: // PDO::FETCH_LAZY - object|false - // This actually returns a PDORow object, but that class is - // undocumented, and its attributes are all dynamic anyway - return new Union([ - new TObject(), - new TFalse(), - ]); - - case 11: // PDO::FETCH_NAMED - array>|false - return new Union([ - new TArray([ - Type::getString(), - new Union([ - new TScalar(), - new TNull(), - Type::getListAtomic( - new Union([ - new TScalar(), - new TNull(), - ]), - ), - ]), + ]), + new TFalse(), + ]), + 6 => Type::getBool(), + 7 => new Union([ + new TScalar(), + new TNull(), + new TFalse(), + ]), + 8 => new Union([ + new TObject(), + new TFalse(), + ]), + 1 => new Union([ + new TObject(), + new TFalse(), + ]), + 11 => new Union([ + new TArray([ + Type::getString(), + new Union([ + new TScalar(), + new TNull(), + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), ]), - new TFalse(), - ]); - - case 12: // PDO::FETCH_KEY_PAIR - array - return new Union([ - new TArray([ - Type::getArrayKey(), - new Union([ - new TScalar(), - new TNull(), - ]), + ]), + new TFalse(), + ]), + 12 => new Union([ + new TArray([ + Type::getArrayKey(), + new Union([ + new TScalar(), + new TNull(), ]), - ]); - - case 3: // PDO::FETCH_NUM - list|false - return new Union([ - Type::getListAtomic( - new Union([ - new TScalar(), - new TNull(), - ]), - ), - new TFalse(), - ]); - - case 5: // PDO::FETCH_OBJ - stdClass|false - return new Union([ - new TNamedObject('stdClass'), - new TFalse(), - ]); - } - - return null; + ]), + ]), + 3 => new Union([ + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), + new TFalse(), + ]), + 5 => new Union([ + new TNamedObject('stdClass'), + new TFalse(), + ]), + default => null, + }; } private static function handleFetchAll(MethodReturnTypeProviderEvent $event): ?Union @@ -183,120 +160,101 @@ private static function handleFetchAll(MethodReturnTypeProviderEvent $event): ?U ) { $fetch_class_name = $second_arg_type->getSingleStringLiteral()->value; } - - switch ($fetch_mode) { - case 2: // PDO::FETCH_ASSOC - list> - return new Union([ - Type::getListAtomic( - new Union([ - new TArray([ - Type::getString(), - new Union([ - new TScalar(), - new TNull(), - ]), + return match ($fetch_mode) { + 2 => new Union([ + Type::getListAtomic( + new Union([ + new TArray([ + Type::getString(), + new Union([ + new TScalar(), + new TNull(), ]), ]), - ), - ]); - - case 4: // PDO::FETCH_BOTH - list> - return new Union([ - Type::getListAtomic( - new Union([ - new TArray([ - Type::getArrayKey(), - new Union([ - new TScalar(), - new TNull(), - ]), + ]), + ), + ]), + 4 => new Union([ + Type::getListAtomic( + new Union([ + new TArray([ + Type::getArrayKey(), + new Union([ + new TScalar(), + new TNull(), ]), ]), - ), - ]); - - case 6: // PDO::FETCH_BOUND - list - return new Union([ - Type::getListAtomic( - Type::getBool(), - ), - ]); - - case 7: // PDO::FETCH_COLUMN - list - return new Union([ - Type::getListAtomic( - new Union([ - new TScalar(), - new TNull(), - ]), - ), - ]); - - case 8: // PDO::FETCH_CLASS - list - return new Union([ - Type::getListAtomic( - new Union([ - $fetch_class_name ? new TNamedObject($fetch_class_name) : new TObject(), - ]), - ), - ]); - - case 11: // PDO::FETCH_NAMED - list>> - return new Union([ - Type::getListAtomic( - new Union([ - new TArray([ - Type::getString(), - new Union([ - new TScalar(), - new TNull(), - Type::getListAtomic( - new Union([ - new TScalar(), - new TNull(), - ]), - ), - ]), + ]), + ), + ]), + 6 => new Union([ + Type::getListAtomic( + Type::getBool(), + ), + ]), + 7 => new Union([ + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), + ]), + 8 => new Union([ + Type::getListAtomic( + new Union([ + $fetch_class_name ? new TNamedObject($fetch_class_name) : new TObject(), + ]), + ), + ]), + 11 => new Union([ + Type::getListAtomic( + new Union([ + new TArray([ + Type::getString(), + new Union([ + new TScalar(), + new TNull(), + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), ]), ]), - ), - ]); - - case 12: // PDO::FETCH_KEY_PAIR - array - return new Union([ - new TArray([ - Type::getArrayKey(), - new Union([ - new TScalar(), - new TNull(), - ]), ]), - ]); - - case 3: // PDO::FETCH_NUM - list> - return new Union([ - Type::getListAtomic( - new Union([ - Type::getListAtomic( - new Union([ - new TScalar(), - new TNull(), - ]), - ), - ]), - ), - ]); - - case 5: // PDO::FETCH_OBJ - list - return new Union([ - Type::getListAtomic( - new Union([ - new TNamedObject('stdClass'), - ]), - ), - ]); - } - - return null; + ), + ]), + 12 => new Union([ + new TArray([ + Type::getArrayKey(), + new Union([ + new TScalar(), + new TNull(), + ]), + ]), + ]), + 3 => new Union([ + Type::getListAtomic( + new Union([ + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), + ]), + ), + ]), + 5 => new Union([ + Type::getListAtomic( + new Union([ + new TNamedObject('stdClass'), + ]), + ), + ]), + default => null, + }; } } diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/SprintfReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/SprintfReturnTypeProvider.php index f74d619fc10..25ba7c18ca2 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/SprintfReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/SprintfReturnTypeProvider.php @@ -239,7 +239,7 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev ); break 2; - } catch (ArgumentCountError $error) { + } catch (ArgumentCountError) { // PHP 8 if (count($dummy) === $provided_placeholders_count) { IssueBuffer::maybeAdd( diff --git a/src/Psalm/Internal/Provider/StatementsProvider.php b/src/Psalm/Internal/Provider/StatementsProvider.php index 90a2a0a143f..b171cd645f1 100644 --- a/src/Psalm/Internal/Provider/StatementsProvider.php +++ b/src/Psalm/Internal/Provider/StatementsProvider.php @@ -33,6 +33,7 @@ use function filemtime; use function hash; use function md5; +use function str_starts_with; use function strlen; use function strpos; @@ -43,13 +44,7 @@ */ final class StatementsProvider { - private FileProvider $file_provider; - - public ?ParserCacheProvider $parser_cache_provider = null; - - private int|bool $this_modified_time; - - private ?FileStorageCacheProvider $file_storage_cache_provider = null; + private readonly int|bool $this_modified_time; /** * @var array> @@ -86,14 +81,11 @@ final class StatementsProvider private static ?Parser $parser = null; public function __construct( - FileProvider $file_provider, - ?ParserCacheProvider $parser_cache_provider = null, - ?FileStorageCacheProvider $file_storage_cache_provider = null, + private readonly FileProvider $file_provider, + public ?ParserCacheProvider $parser_cache_provider = null, + private readonly ?FileStorageCacheProvider $file_storage_cache_provider = null, ) { - $this->file_provider = $file_provider; - $this->parser_cache_provider = $parser_cache_provider; $this->this_modified_time = filemtime(__FILE__); - $this->file_storage_cache_provider = $file_storage_cache_provider; } /** @@ -211,7 +203,7 @@ public function getStatementsForFile( $changed_members = array_map( static function (string $key) use ($file_path_hash): string { - if (strpos($key, 'use:') === 0) { + if (str_starts_with($key, 'use:')) { return $key . ':' . $file_path_hash; } @@ -288,7 +280,7 @@ public function getChangedMembers(): array */ public function addChangedMembers(array $more_changed_members): void { - $this->changed_members = array_merge($more_changed_members, $this->changed_members); + $this->changed_members = [...$more_changed_members, ...$this->changed_members]; } /** @@ -304,7 +296,7 @@ public function getUnchangedSignatureMembers(): array */ public function addUnchangedSignatureMembers(array $more_unchanged_members): void { - $this->unchanged_signature_members = array_merge($more_unchanged_members, $this->unchanged_signature_members); + $this->unchanged_signature_members = [...$more_unchanged_members, ...$this->unchanged_signature_members]; } /** @@ -355,7 +347,7 @@ public function getDeletionRanges(): array */ public function addDiffMap(array $diff_map): void { - $this->diff_map = array_merge($diff_map, $this->diff_map); + $this->diff_map = [...$diff_map, ...$this->diff_map]; } /** @@ -363,7 +355,7 @@ public function addDiffMap(array $diff_map): void */ public function addDeletionRanges(array $deletion_ranges): void { - $this->deletion_ranges = array_merge($deletion_ranges, $this->deletion_ranges); + $this->deletion_ranges = [...$deletion_ranges, ...$this->deletion_ranges]; } public function resetDiffs(): void @@ -429,7 +421,7 @@ public static function parseStatements( try { /** @var list */ $stmts = self::$parser->parse($file_contents, $error_handler) ?: []; - } catch (Throwable $t) { + } catch (Throwable) { $stmts = []; // hope this got caught below @@ -439,7 +431,7 @@ public static function parseStatements( try { /** @var list */ $stmts = self::$parser->parse($file_contents, $error_handler) ?: []; - } catch (Throwable $t) { + } catch (Throwable) { $stmts = []; // hope this got caught below diff --git a/src/Psalm/Internal/Scanner/DocblockParser.php b/src/Psalm/Internal/Scanner/DocblockParser.php index aea5ef4ea69..3161c0373af 100644 --- a/src/Psalm/Internal/Scanner/DocblockParser.php +++ b/src/Psalm/Internal/Scanner/DocblockParser.php @@ -19,7 +19,10 @@ use function preg_match; use function preg_replace; use function rtrim; +use function str_contains; +use function str_ends_with; use function str_replace; +use function str_starts_with; use function strlen; use function strpos; use function strspn; @@ -44,21 +47,21 @@ public static function parse(string $docblock, int $offsetStart): ParsedDocblock // Strip off comments. $docblock = trim($docblock); - if (strpos($docblock, '/**') === 0) { + if (str_starts_with($docblock, '/**')) { $docblock = substr($docblock, 3); } - if (substr($docblock, -2) === '*/') { + if (str_ends_with($docblock, '*/')) { $docblock = substr($docblock, 0, -2); - if (substr($docblock, -1) === '*') { + if (str_ends_with($docblock, '*')) { $docblock = substr($docblock, 0, -1); } } // Normalize multi-line @specials. $lines = explode("\n", str_replace("\t", ' ', $docblock)); - $has_r = strpos($docblock, "\r") === false ? false : true; + $has_r = !str_contains($docblock, "\r") ? false : true; $special = []; @@ -66,7 +69,7 @@ public static function parse(string $docblock, int $offsetStart): ParsedDocblock $last = false; foreach ($lines as $k => $line) { - if (strpos($line, '@') !== false && preg_match('/^ *\*?\s*@\w/', $line)) { + if (str_contains($line, '@') && preg_match('/^ *\*?\s*@\w/', $line)) { $last = $k; } elseif (trim($line) === '') { $last = false; @@ -103,7 +106,7 @@ public static function parse(string $docblock, int $offsetStart): ParsedDocblock [$type] = $type_info; [$data, $data_offset] = $data_info; - if (strpos($data, '*') !== false) { + if (str_contains($data, '*')) { $data = rtrim((string) preg_replace('/^ *\*\s*$/m', '', $data)); } diff --git a/src/Psalm/Internal/Scanner/FileScanner.php b/src/Psalm/Internal/Scanner/FileScanner.php index aaf92dd670f..d8ba100c47f 100644 --- a/src/Psalm/Internal/Scanner/FileScanner.php +++ b/src/Psalm/Internal/Scanner/FileScanner.php @@ -20,17 +20,8 @@ */ class FileScanner implements FileSource { - public string $file_path; - - public string $file_name; - - public bool $will_analyze; - - public function __construct(string $file_path, string $file_name, bool $will_analyze) + public function __construct(public string $file_path, public string $file_name, public bool $will_analyze) { - $this->file_path = $file_path; - $this->file_name = $file_name; - $this->will_analyze = $will_analyze; } public function scan( diff --git a/src/Psalm/Internal/Scanner/ParsedDocblock.php b/src/Psalm/Internal/Scanner/ParsedDocblock.php index e495e749fd5..61e27b076a9 100644 --- a/src/Psalm/Internal/Scanner/ParsedDocblock.php +++ b/src/Psalm/Internal/Scanner/ParsedDocblock.php @@ -12,24 +12,14 @@ */ final class ParsedDocblock { - public string $description; - - public string $first_line_padding; - - /** @var array> */ - public array $tags = []; - /** @var array> */ public array $combined_tags = []; private static bool $shouldAddNewLineBetweenAnnotations = true; /** @param array> $tags */ - public function __construct(string $description, array $tags, string $first_line_padding = '') + public function __construct(public string $description, public array $tags, public string $first_line_padding = '') { - $this->description = $description; - $this->tags = $tags; - $this->first_line_padding = $first_line_padding; } public function render(string $left_padding): string diff --git a/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php b/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php index e1518a8a0e6..2ca354dc68f 100644 --- a/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php +++ b/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php @@ -18,8 +18,8 @@ use function count; use function is_string; +use function str_contains; use function str_replace; -use function strpos; use function strtolower; /** @@ -178,10 +178,10 @@ static function ( } if (($mapped_type = $map[''] ?? null) && is_string($mapped_type)) { - if (strpos($mapped_type, '@') !== false) { + if (str_contains($mapped_type, '@')) { $mapped_type = str_replace('@', $offset_arg_value, $mapped_type); - if (strpos($mapped_type, '.') === false) { + if (!str_contains($mapped_type, '.')) { return new Union([ new TNamedObject($mapped_type), ]); @@ -320,10 +320,10 @@ static function ( } if (($mapped_type = $map[''] ?? null) && is_string($mapped_type)) { - if (strpos($mapped_type, '@') !== false) { + if (str_contains($mapped_type, '@')) { $mapped_type = str_replace('@', $offset_arg_value, $mapped_type); - if (strpos($mapped_type, '.') === false) { + if (!str_contains($mapped_type, '.')) { return new Union([ new TNamedObject($mapped_type), ]); diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php index 656a2c9f359..5d00c814497 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php @@ -12,13 +12,7 @@ */ final class ArrayOffsetFetch extends UnresolvedConstantComponent { - public UnresolvedConstantComponent $array; - - public UnresolvedConstantComponent $offset; - - public function __construct(UnresolvedConstantComponent $left, UnresolvedConstantComponent $right) + public function __construct(public UnresolvedConstantComponent $array, public UnresolvedConstantComponent $offset) { - $this->array = $left; - $this->offset = $right; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArraySpread.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArraySpread.php index f0ca5d0b6ca..8861350a971 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArraySpread.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArraySpread.php @@ -12,10 +12,7 @@ */ final class ArraySpread extends UnresolvedConstantComponent { - public UnresolvedConstantComponent $array; - - public function __construct(UnresolvedConstantComponent $array) + public function __construct(public UnresolvedConstantComponent $array) { - $this->array = $array; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php index 7bc11b7d284..8ae8fd24f2a 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php @@ -12,12 +12,8 @@ */ final class ArrayValue extends UnresolvedConstantComponent { - /** @var array */ - public array $entries; - /** @param list $entries */ - public function __construct(array $entries) + public function __construct(public array $entries) { - $this->entries = $entries; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php index 6b4f4ec9eb1..d1bbc75d198 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php @@ -12,13 +12,7 @@ */ final class ClassConstant extends UnresolvedConstantComponent { - public string $fqcln; - - public string $name; - - public function __construct(string $fqcln, string $name) + public function __construct(public string $fqcln, public string $name) { - $this->fqcln = $fqcln; - $this->name = $name; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php index b3d59fc8834..fcd76336eb9 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php @@ -12,13 +12,7 @@ */ final class Constant extends UnresolvedConstantComponent { - public string $name; - - public bool $is_fully_qualified; - - public function __construct(string $name, bool $is_fully_qualified) + public function __construct(public string $name, public bool $is_fully_qualified) { - $this->name = $name; - $this->is_fully_qualified = $is_fully_qualified; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/EnumPropertyFetch.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/EnumPropertyFetch.php index a9c93d66e38..44f06bf4f12 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/EnumPropertyFetch.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/EnumPropertyFetch.php @@ -12,13 +12,7 @@ */ abstract class EnumPropertyFetch extends UnresolvedConstantComponent { - public string $fqcln; - - public string $case; - - public function __construct(string $fqcln, string $case) + public function __construct(public string $fqcln, public string $case) { - $this->fqcln = $fqcln; - $this->case = $case; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php index 17198114647..6501589a782 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php @@ -12,13 +12,7 @@ */ final class KeyValuePair extends UnresolvedConstantComponent { - public ?UnresolvedConstantComponent $key = null; - - public UnresolvedConstantComponent $value; - - public function __construct(?UnresolvedConstantComponent $key, UnresolvedConstantComponent $value) + public function __construct(public ?UnresolvedConstantComponent $key, public UnresolvedConstantComponent $value) { - $this->key = $key; - $this->value = $value; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php index 7f6b7589158..de23446a81b 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php @@ -12,10 +12,7 @@ */ final class ScalarValue extends UnresolvedConstantComponent { - public string|int|float|bool|null $value = null; - - public function __construct(string|int|float|bool|null $value) + public function __construct(public string|int|float|bool|null $value) { - $this->value = $value; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php index 40acb62ebe9..45c4791d731 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php @@ -15,13 +15,7 @@ abstract class UnresolvedBinaryOp extends UnresolvedConstantComponent { use ImmutableNonCloneableTrait; - public UnresolvedConstantComponent $left; - - public UnresolvedConstantComponent $right; - - public function __construct(UnresolvedConstantComponent $left, UnresolvedConstantComponent $right) + public function __construct(public UnresolvedConstantComponent $left, public UnresolvedConstantComponent $right) { - $this->left = $left; - $this->right = $right; } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php index f34383287c4..3e1cf7ca913 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php @@ -15,19 +15,7 @@ final class UnresolvedTernary extends UnresolvedConstantComponent { use ImmutableNonCloneableTrait; - public UnresolvedConstantComponent $cond; - - public ?UnresolvedConstantComponent $if = null; - - public UnresolvedConstantComponent $else; - - public function __construct( - UnresolvedConstantComponent $cond, - ?UnresolvedConstantComponent $if, - UnresolvedConstantComponent $else, - ) { - $this->cond = $cond; - $this->if = $if; - $this->else = $else; + public function __construct(public UnresolvedConstantComponent $cond, public ?UnresolvedConstantComponent $if, public UnresolvedConstantComponent $else) + { } } diff --git a/src/Psalm/Internal/Scope/CaseScope.php b/src/Psalm/Internal/Scope/CaseScope.php index bb93b265589..371f01bc360 100644 --- a/src/Psalm/Internal/Scope/CaseScope.php +++ b/src/Psalm/Internal/Scope/CaseScope.php @@ -12,16 +12,13 @@ */ final class CaseScope { - public Context $parent_context; - /** * @var array|null */ public ?array $break_vars = null; - public function __construct(Context $parent_context) + public function __construct(public Context $parent_context) { - $this->parent_context = $parent_context; } public function __destruct() diff --git a/src/Psalm/Internal/Scope/FinallyScope.php b/src/Psalm/Internal/Scope/FinallyScope.php index d02d2bf01ef..a587c385bf9 100644 --- a/src/Psalm/Internal/Scope/FinallyScope.php +++ b/src/Psalm/Internal/Scope/FinallyScope.php @@ -11,16 +11,10 @@ */ final class FinallyScope { - /** - * @var array - */ - public array $vars_in_scope = []; - /** * @param array $vars_in_scope */ - public function __construct(array $vars_in_scope) + public function __construct(public array $vars_in_scope) { - $this->vars_in_scope = $vars_in_scope; } } diff --git a/src/Psalm/Internal/Scope/IfConditionalScope.php b/src/Psalm/Internal/Scope/IfConditionalScope.php index 386d8daf034..502979c06e9 100644 --- a/src/Psalm/Internal/Scope/IfConditionalScope.php +++ b/src/Psalm/Internal/Scope/IfConditionalScope.php @@ -12,39 +12,12 @@ */ final class IfConditionalScope { - public Context $if_context; - - public Context $post_if_context; - - /** - * @var array - */ - public array $cond_referenced_var_ids; - - /** - * @var array - */ - public array $assigned_in_conditional_var_ids; - - /** @var list */ - public array $entry_clauses; - /** * @param array $cond_referenced_var_ids * @param array $assigned_in_conditional_var_ids * @param list $entry_clauses */ - public function __construct( - Context $if_context, - Context $post_if_context, - array $cond_referenced_var_ids, - array $assigned_in_conditional_var_ids, - array $entry_clauses, - ) { - $this->if_context = $if_context; - $this->post_if_context = $post_if_context; - $this->cond_referenced_var_ids = $cond_referenced_var_ids; - $this->assigned_in_conditional_var_ids = $assigned_in_conditional_var_ids; - $this->entry_clauses = $entry_clauses; + public function __construct(public Context $if_context, public Context $post_if_context, public array $cond_referenced_var_ids, public array $assigned_in_conditional_var_ids, public array $entry_clauses) + { } } diff --git a/src/Psalm/Internal/Scope/LoopScope.php b/src/Psalm/Internal/Scope/LoopScope.php index dbd45a88217..d599737e81e 100644 --- a/src/Psalm/Internal/Scope/LoopScope.php +++ b/src/Psalm/Internal/Scope/LoopScope.php @@ -14,10 +14,6 @@ final class LoopScope { public int $iteration_count = 0; - public Context $loop_context; - - public Context $loop_parent_context; - /** * @var array */ @@ -53,10 +49,8 @@ final class LoopScope */ public array $final_actions = []; - public function __construct(Context $loop_context, Context $parent_context) + public function __construct(public Context $loop_context, public Context $loop_parent_context) { - $this->loop_context = $loop_context; - $this->loop_parent_context = $parent_context; } public function __destruct() diff --git a/src/Psalm/Internal/Stubs/Generator/ClassLikeStubGenerator.php b/src/Psalm/Internal/Stubs/Generator/ClassLikeStubGenerator.php index dfbbc10c5e1..7a110f6a32e 100644 --- a/src/Psalm/Internal/Stubs/Generator/ClassLikeStubGenerator.php +++ b/src/Psalm/Internal/Stubs/Generator/ClassLikeStubGenerator.php @@ -162,17 +162,11 @@ private static function getPropertyNodes(ClassLikeStorage $storage): array $property_nodes = []; foreach ($storage->properties as $property_name => $property_storage) { - switch ($property_storage->visibility) { - case ClassLikeAnalyzer::VISIBILITY_PRIVATE: - $flag = PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE; - break; - case ClassLikeAnalyzer::VISIBILITY_PROTECTED: - $flag = PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED; - break; - default: - $flag = PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC; - break; - } + $flag = match ($property_storage->visibility) { + ClassLikeAnalyzer::VISIBILITY_PRIVATE => PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE, + ClassLikeAnalyzer::VISIBILITY_PROTECTED => PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED, + default => PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC, + }; $docblock = new ParsedDocblock('', []); @@ -227,17 +221,11 @@ private static function getMethodNodes(ClassLikeStorage $storage): array { throw new UnexpectedValueException('very bad'); } - switch ($method_storage->visibility) { - case ReflectionProperty::IS_PRIVATE: - $flag = PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE; - break; - case ReflectionProperty::IS_PROTECTED: - $flag = PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED; - break; - default: - $flag = PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC; - break; - } + $flag = match ($method_storage->visibility) { + ReflectionProperty::IS_PRIVATE => PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE, + ReflectionProperty::IS_PROTECTED => PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED, + default => PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC, + }; $docblock = new ParsedDocblock('', []); diff --git a/src/Psalm/Internal/Stubs/Generator/StubsGenerator.php b/src/Psalm/Internal/Stubs/Generator/StubsGenerator.php index 528c2e92ed8..301c2979d0b 100644 --- a/src/Psalm/Internal/Stubs/Generator/StubsGenerator.php +++ b/src/Psalm/Internal/Stubs/Generator/StubsGenerator.php @@ -63,12 +63,12 @@ public static function getAll( $psalm_base = dirname(__DIR__, 5); foreach ($class_provider->getAll() as $storage) { - if (strpos($storage->name, 'Psalm\\') === 0) { + if (str_starts_with($storage->name, 'Psalm\\')) { continue; } if ($storage->location - && strpos($storage->location->file_path, $psalm_base) === 0 + && str_starts_with($storage->location->file_path, $psalm_base) ) { continue; } @@ -97,7 +97,7 @@ public static function getAll( foreach ($codebase->functions->getAllStubbedFunctions() as $function_storage) { if ($function_storage->location - && strpos($function_storage->location->file_path, $psalm_base) === 0 + && str_starts_with($function_storage->location->file_path, $psalm_base) ) { continue; } @@ -143,7 +143,7 @@ public static function getAll( } foreach ($file_provider->getAll() as $file_storage) { - if (strpos($file_storage->file_path, $psalm_base) === 0) { + if (str_starts_with($file_storage->file_path, $psalm_base)) { continue; } diff --git a/src/Psalm/Internal/Type/ArrayType.php b/src/Psalm/Internal/Type/ArrayType.php index f115fcc9879..a0a9cebb2c9 100644 --- a/src/Psalm/Internal/Type/ArrayType.php +++ b/src/Psalm/Internal/Type/ArrayType.php @@ -17,20 +17,8 @@ */ final class ArrayType { - public Union $key; - - public Union $value; - - public bool $is_list; - - public ?int $count = null; - - public function __construct(Union $key, Union $value, bool $is_list, ?int $count) + public function __construct(public Union $key, public Union $value, public bool $is_list, public ?int $count) { - $this->key = $key; - $this->value = $value; - $this->is_list = $is_list; - $this->count = $count; } /** diff --git a/src/Psalm/Internal/Type/AssertionReconciler.php b/src/Psalm/Internal/Type/AssertionReconciler.php index 1cc7af0733c..851dc29c1c6 100644 --- a/src/Psalm/Internal/Type/AssertionReconciler.php +++ b/src/Psalm/Internal/Type/AssertionReconciler.php @@ -64,7 +64,6 @@ use function array_intersect_key; use function array_merge; use function count; -use function get_class; use function is_string; /** @@ -830,7 +829,7 @@ private static function refineContainedAtomicWithAnother( bool $type_coerced, ): ?Atomic { if ($type_coerced - && get_class($type_2_atomic) === TNamedObject::class + && $type_2_atomic::class === TNamedObject::class && $type_1_atomic instanceof TGenericObject ) { // this is a hack - it's not actually rigorous, as the params may be different @@ -952,7 +951,7 @@ private static function handleLiteralEquality( $existing_var_type = $existing_var_type->getBuilder(); foreach ($existing_var_atomic_types as $atomic_key => $atomic_type) { - if (get_class($atomic_type) === TNamedObject::class + if ($atomic_type::class === TNamedObject::class && $atomic_type->value === $fq_enum_name ) { $can_be_equal = true; @@ -1547,7 +1546,7 @@ private static function handleIsA( if ($assertion_type instanceof TTemplateParamClass) { return [new TTemplateParam( $assertion_type->param_name, - new Union([$assertion_type->as_type ? $assertion_type->as_type : new TObject()]), + new Union([$assertion_type->as_type ?: new TObject()]), $assertion_type->defining_class, )]; } diff --git a/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php b/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php index 11974afe85c..e024bc95fc0 100644 --- a/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php +++ b/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php @@ -43,7 +43,6 @@ use function array_values; use function assert; use function count; -use function get_class; use function strtolower; /** @@ -112,10 +111,10 @@ public static function isContainedBy( && !$container_type_part->extra_types && $input_type_part instanceof TMixed) ) { - if (get_class($input_type_part) === TMixed::class + if ($input_type_part::class === TMixed::class && ( - get_class($container_type_part) === TEmptyMixed::class - || get_class($container_type_part) === TNonEmptyMixed::class + $container_type_part::class === TEmptyMixed::class + || $container_type_part::class === TNonEmptyMixed::class ) ) { if ($atomic_comparison_result) { @@ -311,14 +310,14 @@ public static function isContainedBy( ); } - if (get_class($container_type_part) === TNamedObject::class + if ($container_type_part::class === TNamedObject::class && $input_type_part instanceof TEnumCase && $input_type_part->value === $container_type_part->value ) { return true; } - if (get_class($input_type_part) === TNamedObject::class + if ($input_type_part::class === TNamedObject::class && $container_type_part instanceof TEnumCase && $input_type_part->value === $container_type_part->value ) { @@ -381,8 +380,8 @@ public static function isContainedBy( return true; } - if (get_class($input_type_part) === TObject::class - && get_class($container_type_part) === TObject::class + if ($input_type_part::class === TObject::class + && $container_type_part::class === TObject::class ) { return true; } @@ -819,9 +818,9 @@ public static function canBeIdentical( ); } - if ((get_class($type1_part) === TArray::class + if (($type1_part::class === TArray::class && $type2_part instanceof TNonEmptyArray) - || (get_class($type2_part) === TArray::class + || ($type2_part::class === TArray::class && $type1_part instanceof TNonEmptyArray) ) { return UnionTypeComparator::canExpressionTypesBeIdentical( diff --git a/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php b/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php index 82aa62d9108..380496d12de 100644 --- a/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php +++ b/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php @@ -210,7 +210,7 @@ public static function isNotExplicitlyCallableTypeCallable( if (!$codebase->methods->hasStorage($method_id)) { return false; } - } catch (Exception $e) { + } catch (Exception) { return false; } } @@ -305,7 +305,7 @@ public static function getCallableFromAtomic( $return_type, $function_storage->pure, ); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { if (InternalCallMapHandler::inCallMap($input_type_part->value)) { $args = []; @@ -370,7 +370,7 @@ public static function getCallableFromAtomic( $converted_return_type, $method_storage->pure, ); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { // do nothing } } diff --git a/src/Psalm/Internal/Type/Comparator/ClassLikeStringComparator.php b/src/Psalm/Internal/Type/Comparator/ClassLikeStringComparator.php index e63dd39a0f6..1c9b4ed1ab9 100644 --- a/src/Psalm/Internal/Type/Comparator/ClassLikeStringComparator.php +++ b/src/Psalm/Internal/Type/Comparator/ClassLikeStringComparator.php @@ -11,8 +11,6 @@ use Psalm\Type\Atomic\TNamedObject; use Psalm\Type\Atomic\TTemplateParamClass; -use function get_class; - /** * @internal */ @@ -36,7 +34,7 @@ public static function isContainedBy( } if ($container_type_part instanceof TTemplateParamClass - && get_class($input_type_part) === TClassString::class + && $input_type_part::class === TClassString::class ) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = true; diff --git a/src/Psalm/Internal/Type/Comparator/IntegerRangeComparator.php b/src/Psalm/Internal/Type/Comparator/IntegerRangeComparator.php index ea0ff25f0a8..e9d150d0d21 100644 --- a/src/Psalm/Internal/Type/Comparator/IntegerRangeComparator.php +++ b/src/Psalm/Internal/Type/Comparator/IntegerRangeComparator.php @@ -13,7 +13,6 @@ use UnexpectedValueException; use function count; -use function get_class; /** * @internal @@ -59,11 +58,11 @@ public static function isContainedByUnion( ); if (isset($container_atomic_types['int'])) { - if (get_class($container_atomic_types['int']) === TInt::class) { + if ($container_atomic_types['int']::class === TInt::class) { return true; } - if (get_class($container_atomic_types['int']) === TNonspecificLiteralInt::class) { + if ($container_atomic_types['int']::class === TNonspecificLiteralInt::class) { return true; } diff --git a/src/Psalm/Internal/Type/Comparator/ObjectComparator.php b/src/Psalm/Internal/Type/Comparator/ObjectComparator.php index 5689350663b..73454ae8a88 100644 --- a/src/Psalm/Internal/Type/Comparator/ObjectComparator.php +++ b/src/Psalm/Internal/Type/Comparator/ObjectComparator.php @@ -18,6 +18,7 @@ use function count; use function current; use function in_array; +use function str_starts_with; use function strpos; use function strtolower; use function substr; @@ -43,8 +44,8 @@ public static function isShallowlyContainedBy( && $container_type_part->defining_class != $input_type_part->defining_class && 1 == count($container_type_part->as->getAtomicTypes()) && 1 == count($input_type_part->as->getAtomicTypes())) { - $containerDefinedInFunction = strpos($container_type_part->defining_class, 'fn-') === 0; - $inputDefinedInFunction = strpos($input_type_part->defining_class, 'fn-') === 0; + $containerDefinedInFunction = str_starts_with($container_type_part->defining_class, 'fn-'); + $inputDefinedInFunction = str_starts_with($input_type_part->defining_class, 'fn-'); if ($inputDefinedInFunction) { $separatorPos = strpos($input_type_part->defining_class, '::'); if ($separatorPos === false) { @@ -187,11 +188,11 @@ private static function isIntersectionShallowlyContainedBy( && $intersection_input_type instanceof TTemplateParam ) { if (!$allow_interface_equality) { - if (strpos($intersection_container_type->defining_class, 'fn-') === 0 - || strpos($intersection_input_type->defining_class, 'fn-') === 0 + if (str_starts_with($intersection_container_type->defining_class, 'fn-') + || str_starts_with($intersection_input_type->defining_class, 'fn-') ) { - if (strpos($intersection_input_type->defining_class, 'fn-') === 0 - && strpos($intersection_container_type->defining_class, 'fn-') === 0 + if (str_starts_with($intersection_input_type->defining_class, 'fn-') + && str_starts_with($intersection_container_type->defining_class, 'fn-') && $intersection_input_type->defining_class !== $intersection_container_type->defining_class ) { @@ -215,11 +216,11 @@ private static function isIntersectionShallowlyContainedBy( if ($intersection_container_type->param_name !== $intersection_input_type->param_name || ($intersection_container_type->defining_class !== $intersection_input_type->defining_class - && strpos($intersection_input_type->defining_class, 'fn-') !== 0 - && strpos($intersection_container_type->defining_class, 'fn-') !== 0) + && !str_starts_with($intersection_input_type->defining_class, 'fn-') + && !str_starts_with($intersection_container_type->defining_class, 'fn-')) ) { - if (strpos($intersection_input_type->defining_class, 'fn-') === 0 - || strpos($intersection_container_type->defining_class, 'fn-') === 0 + if (str_starts_with($intersection_input_type->defining_class, 'fn-') + || str_starts_with($intersection_container_type->defining_class, 'fn-') ) { return false; } diff --git a/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php b/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php index fdef3c46fc7..f6ba06538c7 100644 --- a/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php +++ b/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php @@ -40,7 +40,6 @@ use Psalm\Type\Atomic\TTraitString; use Psalm\Type\Atomic\TTrue; -use function get_class; use function is_numeric; use function strtolower; @@ -57,26 +56,26 @@ public static function isContainedBy( bool $allow_float_int_equality = true, ?TypeComparisonResult $atomic_comparison_result = null, ): bool { - if (get_class($container_type_part) === TString::class + if ($container_type_part::class === TString::class && $input_type_part instanceof TString ) { return true; } - if (get_class($container_type_part) === TInt::class + if ($container_type_part::class === TInt::class && $input_type_part instanceof TInt ) { return true; } - if (get_class($container_type_part) === TFloat::class + if ($container_type_part::class === TFloat::class && $input_type_part instanceof TFloat ) { return true; } if ($container_type_part instanceof TNonEmptyString - && get_class($input_type_part) === TString::class + && $input_type_part::class === TString::class ) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = true; @@ -119,10 +118,10 @@ public static function isContainedBy( } if ($input_type_part instanceof TCallableString - && (get_class($container_type_part) === TSingleLetter::class - || get_class($container_type_part) === TNonEmptyString::class - || get_class($container_type_part) === TNonFalsyString::class - || get_class($container_type_part) === TLowercaseString::class) + && ($container_type_part::class === TSingleLetter::class + || $container_type_part::class === TNonEmptyString::class + || $container_type_part::class === TNonFalsyString::class + || $container_type_part::class === TLowercaseString::class) ) { return true; } @@ -281,12 +280,12 @@ public static function isContainedBy( return true; } - if (get_class($container_type_part) === TFloat::class && $input_type_part instanceof TLiteralFloat) { + if ($container_type_part::class === TFloat::class && $input_type_part instanceof TLiteralFloat) { return true; } - if ((get_class($container_type_part) === TNonEmptyString::class - || get_class($container_type_part) === TNonEmptyNonspecificLiteralString::class) + if (($container_type_part::class === TNonEmptyString::class + || $container_type_part::class === TNonEmptyNonspecificLiteralString::class) && $input_type_part instanceof TNonFalsyString ) { return true; @@ -323,15 +322,15 @@ public static function isContainedBy( return false; } - if ((get_class($container_type_part) === TNonEmptyString::class - || get_class($container_type_part) === TNonFalsyString::class - || get_class($container_type_part) === TSingleLetter::class) + if (($container_type_part::class === TNonEmptyString::class + || $container_type_part::class === TNonFalsyString::class + || $container_type_part::class === TSingleLetter::class) && $input_type_part instanceof TLiteralString ) { return true; } - if (get_class($input_type_part) === TInt::class && $container_type_part instanceof TLiteralInt) { + if ($input_type_part::class === TInt::class && $container_type_part instanceof TLiteralInt) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = true; $atomic_comparison_result->type_coerced_from_scalar = true; @@ -368,7 +367,7 @@ public static function isContainedBy( return false; } - if (get_class($input_type_part) === TFloat::class && $container_type_part instanceof TLiteralFloat) { + if ($input_type_part::class === TFloat::class && $container_type_part instanceof TLiteralFloat) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = true; $atomic_comparison_result->type_coerced_from_scalar = true; @@ -377,8 +376,8 @@ public static function isContainedBy( return false; } - if ((get_class($input_type_part) === TString::class - || get_class($input_type_part) === TSingleLetter::class + if (($input_type_part::class === TString::class + || $input_type_part::class === TSingleLetter::class || $input_type_part instanceof TNonEmptyString || $input_type_part instanceof TNonspecificLiteralString) && $container_type_part instanceof TLiteralString @@ -423,7 +422,7 @@ public static function isContainedBy( } if ($container_type_part instanceof TTraitString - && (get_class($input_type_part) === TString::class + && ($input_type_part::class === TString::class || $input_type_part instanceof TNonEmptyString || $input_type_part instanceof TNonEmptyNonspecificLiteralString) ) { @@ -436,15 +435,15 @@ public static function isContainedBy( if (($input_type_part instanceof TClassString || $input_type_part instanceof TLiteralClassString) - && (get_class($container_type_part) === TSingleLetter::class - || get_class($container_type_part) === TNonEmptyString::class - || get_class($container_type_part) === TNonFalsyString::class) + && ($container_type_part::class === TSingleLetter::class + || $container_type_part::class === TNonEmptyString::class + || $container_type_part::class === TNonFalsyString::class) ) { return true; } if ($input_type_part instanceof TNumericString - && get_class($container_type_part) === TNonEmptyString::class + && $container_type_part::class === TNonEmptyString::class ) { return true; } @@ -503,7 +502,7 @@ public static function isContainedBy( } if ($input_type_part instanceof TLowercaseString - && get_class($container_type_part) === TNonEmptyString::class) { + && $container_type_part::class === TNonEmptyString::class) { return false; } diff --git a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php index b916caa8e73..25427382198 100644 --- a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php +++ b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php @@ -36,7 +36,6 @@ use function array_merge; use function array_values; use function count; -use function get_class; use function strtolower; /** @@ -182,7 +181,7 @@ public static function reconcile( $iterable->type_params[1], ], )); - } elseif ($assertion_type !== null && get_class($assertion_type) === TInt::class + } elseif ($assertion_type !== null && $assertion_type::class === TInt::class && isset($existing_var_type->getAtomicTypes()['array-key']) && !$is_equality ) { @@ -368,7 +367,7 @@ private static function handleLiteralNegatedEquality( } if (isset($existing_var_type->getAtomicTypes()['int']) - && get_class($existing_var_type->getAtomicTypes()['int']) === Type\Atomic\TInt::class + && $existing_var_type->getAtomicTypes()['int']::class === Type\Atomic\TInt::class ) { $redundant = false; //this may be used to generate a range containing any int except the one that was asserted against @@ -391,7 +390,7 @@ private static function handleLiteralNegatedEquality( } elseif ($assertion_type->value === "") { $existing_var_type->addType(new TNonEmptyString()); } - } elseif (get_class($assertion_type) === TLiteralString::class) { + } elseif ($assertion_type::class === TLiteralString::class) { $scalar_var_type = $assertion_type; } } elseif ($assertion_type instanceof TLiteralFloat) { @@ -411,7 +410,7 @@ private static function handleLiteralNegatedEquality( $case_name = $assertion_type->case_name; foreach ($existing_var_type->getAtomicTypes() as $atomic_key => $atomic_type) { - if (get_class($atomic_type) === TNamedObject::class + if ($atomic_type::class === TNamedObject::class && $atomic_type->value === $fq_enum_name ) { $codebase = $statements_analyzer->getCodebase(); diff --git a/src/Psalm/Internal/Type/ParseTree.php b/src/Psalm/Internal/Type/ParseTree.php index 5693203547a..d9dd689d29d 100644 --- a/src/Psalm/Internal/Type/ParseTree.php +++ b/src/Psalm/Internal/Type/ParseTree.php @@ -14,13 +14,10 @@ class ParseTree */ public array $children = []; - public ?ParseTree $parent = null; - public bool $possibly_undefined = false; - public function __construct(?ParseTree $parent = null) + public function __construct(public ?ParseTree $parent = null) { - $this->parent = $parent; } public function __destruct() diff --git a/src/Psalm/Internal/Type/ParseTree/CallableTree.php b/src/Psalm/Internal/Type/ParseTree/CallableTree.php index 6196c72d760..96c050e77bc 100644 --- a/src/Psalm/Internal/Type/ParseTree/CallableTree.php +++ b/src/Psalm/Internal/Type/ParseTree/CallableTree.php @@ -11,13 +11,10 @@ */ final class CallableTree extends ParseTree { - public string $value; - public bool $terminated = false; - public function __construct(string $value, ?ParseTree $parent = null) + public function __construct(public string $value, ?ParseTree $parent = null) { - $this->value = $value; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/ConditionalTree.php b/src/Psalm/Internal/Type/ParseTree/ConditionalTree.php index 6cac672cdb2..7c5d7d3ff21 100644 --- a/src/Psalm/Internal/Type/ParseTree/ConditionalTree.php +++ b/src/Psalm/Internal/Type/ParseTree/ConditionalTree.php @@ -11,11 +11,8 @@ */ final class ConditionalTree extends ParseTree { - public TemplateIsTree $condition; - - public function __construct(TemplateIsTree $condition, ?ParseTree $parent = null) + public function __construct(public TemplateIsTree $condition, ?ParseTree $parent = null) { - $this->condition = $condition; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/GenericTree.php b/src/Psalm/Internal/Type/ParseTree/GenericTree.php index 966e28fb23f..d65bbcf0367 100644 --- a/src/Psalm/Internal/Type/ParseTree/GenericTree.php +++ b/src/Psalm/Internal/Type/ParseTree/GenericTree.php @@ -11,13 +11,10 @@ */ final class GenericTree extends ParseTree { - public string $value; - public bool $terminated = false; - public function __construct(string $value, ?ParseTree $parent = null) + public function __construct(public string $value, ?ParseTree $parent = null) { - $this->value = $value; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/IndexedAccessTree.php b/src/Psalm/Internal/Type/ParseTree/IndexedAccessTree.php index 39891f6f23e..59043c04c4b 100644 --- a/src/Psalm/Internal/Type/ParseTree/IndexedAccessTree.php +++ b/src/Psalm/Internal/Type/ParseTree/IndexedAccessTree.php @@ -11,11 +11,8 @@ */ final class IndexedAccessTree extends ParseTree { - public string $value; - - public function __construct(string $value, ?ParseTree $parent = null) + public function __construct(public string $value, ?ParseTree $parent = null) { - $this->value = $value; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/KeyedArrayPropertyTree.php b/src/Psalm/Internal/Type/ParseTree/KeyedArrayPropertyTree.php index 1c4793306f0..4b1ff376554 100644 --- a/src/Psalm/Internal/Type/ParseTree/KeyedArrayPropertyTree.php +++ b/src/Psalm/Internal/Type/ParseTree/KeyedArrayPropertyTree.php @@ -11,11 +11,8 @@ */ final class KeyedArrayPropertyTree extends ParseTree { - public string $value; - - public function __construct(string $value, ?ParseTree $parent = null) + public function __construct(public string $value, ?ParseTree $parent = null) { - $this->value = $value; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/KeyedArrayTree.php b/src/Psalm/Internal/Type/ParseTree/KeyedArrayTree.php index 9a8e2a69b67..2008fb90300 100644 --- a/src/Psalm/Internal/Type/ParseTree/KeyedArrayTree.php +++ b/src/Psalm/Internal/Type/ParseTree/KeyedArrayTree.php @@ -11,13 +11,10 @@ */ final class KeyedArrayTree extends ParseTree { - public string $value; - public bool $terminated = false; - public function __construct(string $value, ?ParseTree $parent = null) + public function __construct(public string $value, ?ParseTree $parent = null) { - $this->value = $value; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/MethodParamTree.php b/src/Psalm/Internal/Type/ParseTree/MethodParamTree.php index 833f33109fa..9a0a70937e1 100644 --- a/src/Psalm/Internal/Type/ParseTree/MethodParamTree.php +++ b/src/Psalm/Internal/Type/ParseTree/MethodParamTree.php @@ -11,23 +11,14 @@ */ final class MethodParamTree extends ParseTree { - public bool $variadic; - public string $default = ''; - public bool $byref; - - public string $name; - public function __construct( - string $name, - bool $byref, - bool $variadic, + public string $name, + public bool $byref, + public bool $variadic, ?ParseTree $parent = null, ) { - $this->name = $name; - $this->byref = $byref; - $this->variadic = $variadic; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/MethodTree.php b/src/Psalm/Internal/Type/ParseTree/MethodTree.php index 595e3cdfcd7..5e1da1ec6c8 100644 --- a/src/Psalm/Internal/Type/ParseTree/MethodTree.php +++ b/src/Psalm/Internal/Type/ParseTree/MethodTree.php @@ -11,11 +11,8 @@ */ final class MethodTree extends ParseTree { - public string $value; - - public function __construct(string $value, ?ParseTree $parent = null) + public function __construct(public string $value, ?ParseTree $parent = null) { - $this->value = $value; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/TemplateAsTree.php b/src/Psalm/Internal/Type/ParseTree/TemplateAsTree.php index b7d79634880..b27acf72bae 100644 --- a/src/Psalm/Internal/Type/ParseTree/TemplateAsTree.php +++ b/src/Psalm/Internal/Type/ParseTree/TemplateAsTree.php @@ -11,14 +11,8 @@ */ final class TemplateAsTree extends ParseTree { - public string $param_name; - - public string $as; - - public function __construct(string $param_name, string $as, ?ParseTree $parent = null) + public function __construct(public string $param_name, public string $as, ?ParseTree $parent = null) { - $this->param_name = $param_name; - $this->as = $as; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/TemplateIsTree.php b/src/Psalm/Internal/Type/ParseTree/TemplateIsTree.php index 1bff424cacf..07e29c9b149 100644 --- a/src/Psalm/Internal/Type/ParseTree/TemplateIsTree.php +++ b/src/Psalm/Internal/Type/ParseTree/TemplateIsTree.php @@ -11,11 +11,8 @@ */ final class TemplateIsTree extends ParseTree { - public string $param_name; - - public function __construct(string $param_name, ?ParseTree $parent = null) + public function __construct(public string $param_name, ?ParseTree $parent = null) { - $this->param_name = $param_name; $this->parent = $parent; } } diff --git a/src/Psalm/Internal/Type/ParseTree/Value.php b/src/Psalm/Internal/Type/ParseTree/Value.php index 4367469d151..04036e7b9f2 100644 --- a/src/Psalm/Internal/Type/ParseTree/Value.php +++ b/src/Psalm/Internal/Type/ParseTree/Value.php @@ -11,24 +11,15 @@ */ final class Value extends ParseTree { - public string $value; - - public int $offset_start; - - public int $offset_end; - public ?string $text = null; public function __construct( - string $value, - int $offset_start, - int $offset_end, + public string $value, + public int $offset_start, + public int $offset_end, ?string $text, ParseTree $parent = null, ) { - $this->offset_start = $offset_start; - $this->offset_end = $offset_end; - $this->value = $value; $this->parent = $parent; $this->text = $text === $value ? null : $text; } diff --git a/src/Psalm/Internal/Type/ParseTreeCreator.php b/src/Psalm/Internal/Type/ParseTreeCreator.php index 515838b95e8..8e62744fd55 100644 --- a/src/Psalm/Internal/Type/ParseTreeCreator.php +++ b/src/Psalm/Internal/Type/ParseTreeCreator.php @@ -42,19 +42,15 @@ final class ParseTreeCreator private ParseTree $current_leaf; - /** @var array */ - private array $type_tokens; - - private int $type_token_count; + private readonly int $type_token_count; private int $t = 0; /** * @param list $type_tokens */ - public function __construct(array $type_tokens) + public function __construct(private array $type_tokens) { - $this->type_tokens = $type_tokens; $this->type_token_count = count($type_tokens); $this->parse_tree = new Root(); $this->current_leaf = $this->parse_tree; diff --git a/src/Psalm/Internal/Type/SimpleAssertionReconciler.php b/src/Psalm/Internal/Type/SimpleAssertionReconciler.php index 04125509fd3..c748d3edcd0 100644 --- a/src/Psalm/Internal/Type/SimpleAssertionReconciler.php +++ b/src/Psalm/Internal/Type/SimpleAssertionReconciler.php @@ -82,7 +82,6 @@ use function assert; use function count; use function explode; -use function get_class; use function in_array; use function is_int; use function min; @@ -428,7 +427,7 @@ public static function reconcile( ); } - if ($assertion_type && get_class($assertion_type) === TBool::class) { + if ($assertion_type && $assertion_type::class === TBool::class) { return self::reconcileBool( $assertion, $existing_var_type, @@ -467,7 +466,7 @@ public static function reconcile( ); } - if ($assertion_type && get_class($assertion_type) === TString::class) { + if ($assertion_type && $assertion_type::class === TString::class) { return self::reconcileString( $assertion, $existing_var_type, @@ -480,7 +479,7 @@ public static function reconcile( ); } - if ($assertion_type && get_class($assertion_type) === TInt::class) { + if ($assertion_type && $assertion_type::class === TInt::class) { return self::reconcileInt( $assertion, $existing_var_type, @@ -1009,7 +1008,7 @@ private static function reconcileString( foreach ($existing_var_atomic_types as $type) { if ($type instanceof TString) { - if (get_class($type) === TString::class) { + if ($type::class === TString::class) { $type = $type->setFromDocblock(false); } $string_types[] = $type; @@ -1099,7 +1098,7 @@ private static function reconcileInt( foreach ($existing_var_atomic_types as $type) { if ($type instanceof TInt) { - if (get_class($type) === TInt::class) { + if ($type::class === TInt::class) { $type = $type->setFromDocblock(false); } @@ -2505,7 +2504,7 @@ private static function reconcileStringArrayAccess( foreach ($existing_var_atomic_types as $type) { if ($type->isArrayAccessibleWithStringKey($codebase)) { - if (get_class($type) === TArray::class) { + if ($type::class === TArray::class) { $array_types[] = new TNonEmptyArray($type->type_params); } elseif ($type instanceof TKeyedArray && $type->is_list) { $properties = $type->properties; @@ -2570,7 +2569,7 @@ private static function reconcileIntArrayAccess( foreach ($existing_var_atomic_types as $type) { if ($type->isArrayAccessibleWithIntOrStringKey($codebase)) { - if (get_class($type) === TArray::class) { + if ($type::class === TArray::class) { $array_types[] = new TNonEmptyArray($type->type_params); } else { $array_types[] = $type; @@ -2641,13 +2640,13 @@ private static function reconcileCallable( && $codebase->methodExists($type->value . '::__invoke') ) { $callable_types[] = $type; - } elseif (get_class($type) === TString::class - || get_class($type) === TNonEmptyString::class - || get_class($type) === TNonFalsyString::class + } elseif ($type::class === TString::class + || $type::class === TNonEmptyString::class + || $type::class === TNonFalsyString::class ) { $callable_types[] = new TCallableString(); $redundant = false; - } elseif (get_class($type) === TLiteralString::class + } elseif ($type::class === TLiteralString::class && InternalCallMapHandler::inCallMap($type->value) ) { $callable_types[] = $type; @@ -2817,7 +2816,7 @@ private static function reconcileTruthyOrNonEmpty( if (isset($types['mixed'])) { $mixed_atomic_type = $types['mixed']; - if (get_class($mixed_atomic_type) === TMixed::class) { + if ($mixed_atomic_type::class === TMixed::class) { unset($types['mixed']); $types []= new TNonEmptyMixed(); } @@ -2826,7 +2825,7 @@ private static function reconcileTruthyOrNonEmpty( if (isset($types['scalar'])) { $scalar_atomic_type = $types['scalar']; - if (get_class($scalar_atomic_type) === TScalar::class) { + if ($scalar_atomic_type::class === TScalar::class) { unset($types['scalar']); $types []= new TNonEmptyScalar(); } @@ -2835,16 +2834,16 @@ private static function reconcileTruthyOrNonEmpty( if (isset($types['string'])) { $string_atomic_type = $types['string']; - if (get_class($string_atomic_type) === TString::class) { + if ($string_atomic_type::class === TString::class) { unset($types['string']); $types []= new TNonFalsyString(); - } elseif (get_class($string_atomic_type) === TLowercaseString::class) { + } elseif ($string_atomic_type::class === TLowercaseString::class) { unset($types['string']); $types []= new TNonEmptyLowercaseString(); - } elseif (get_class($string_atomic_type) === TNonspecificLiteralString::class) { + } elseif ($string_atomic_type::class === TNonspecificLiteralString::class) { unset($types['string']); $types []= new TNonEmptyNonspecificLiteralString(); - } elseif (get_class($string_atomic_type) === TNonEmptyString::class) { + } elseif ($string_atomic_type::class === TNonEmptyString::class) { unset($types['string']); $types []= new TNonFalsyString(); } diff --git a/src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php b/src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php index bc966c70d47..eb5a4f03e83 100644 --- a/src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php +++ b/src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php @@ -63,9 +63,8 @@ use Psalm\Type\Union; use function assert; -use function get_class; use function max; -use function strpos; +use function str_contains; /** * @internal @@ -97,7 +96,7 @@ public static function reconcile( if (!$existing_var_type->isNullable() && $key - && strpos($key, '[') === false + && !str_contains($key, '[') && (!$existing_var_type->hasMixed() || $existing_var_type->isAlwaysTruthy()) ) { if ($code_location) { @@ -294,7 +293,7 @@ public static function reconcile( ); } - if ($assertion_type && get_class($assertion_type) === TBool::class && !$existing_var_type->hasMixed()) { + if ($assertion_type && $assertion_type::class === TBool::class && !$existing_var_type->hasMixed()) { return self::reconcileBool( $assertion, $existing_var_type, @@ -333,7 +332,7 @@ public static function reconcile( ); } - if ($assertion_type && get_class($assertion_type) === TInt::class && !$existing_var_type->hasMixed()) { + if ($assertion_type && $assertion_type::class === TInt::class && !$existing_var_type->hasMixed()) { return self::reconcileInt( $assertion, $existing_var_type, @@ -346,7 +345,7 @@ public static function reconcile( ); } - if ($assertion_type && get_class($assertion_type) === TString::class && !$existing_var_type->hasMixed()) { + if ($assertion_type && $assertion_type::class === TString::class && !$existing_var_type->hasMixed()) { return self::reconcileString( $assertion, $existing_var_type, @@ -469,7 +468,7 @@ private static function reconcileBool( $redundant = false; } elseif (!$type instanceof TBool - || ($is_equality && get_class($type) === TBool::class) + || ($is_equality && $type::class === TBool::class) ) { if ($type instanceof TScalar) { $redundant = false; @@ -969,7 +968,7 @@ private static function reconcileFalsyOrEmpty( if ($existing_var_type->hasMixed()) { $mixed_atomic_type = $existing_var_type->getAtomicTypes()['mixed']; - if (get_class($mixed_atomic_type) === TMixed::class) { + if ($mixed_atomic_type::class === TMixed::class) { $existing_var_type->removeType('mixed'); $existing_var_type->addType(new TEmptyMixed()); } @@ -978,7 +977,7 @@ private static function reconcileFalsyOrEmpty( if ($existing_var_type->hasScalar()) { $scalar_atomic_type = $existing_var_type->getAtomicTypes()['scalar']; - if (get_class($scalar_atomic_type) === TScalar::class) { + if ($scalar_atomic_type::class === TScalar::class) { $existing_var_type->removeType('scalar'); $existing_var_type->addType(new TEmptyScalar()); } @@ -987,17 +986,17 @@ private static function reconcileFalsyOrEmpty( if ($existing_var_type->hasType('string')) { $string_atomic_type = $existing_var_type->getAtomicTypes()['string']; - if (get_class($string_atomic_type) === TString::class) { + if ($string_atomic_type::class === TString::class) { $existing_var_type->removeType('string'); $existing_var_type->addType(Type::getAtomicStringFromLiteral('')); $existing_var_type->addType(Type::getAtomicStringFromLiteral('0')); - } elseif (get_class($string_atomic_type) === TNonEmptyString::class) { + } elseif ($string_atomic_type::class === TNonEmptyString::class) { $existing_var_type->removeType('string'); $existing_var_type->addType(Type::getAtomicStringFromLiteral('0')); - } elseif (get_class($string_atomic_type) === TNonEmptyLowercaseString::class) { + } elseif ($string_atomic_type::class === TNonEmptyLowercaseString::class) { $existing_var_type->removeType('string'); $existing_var_type->addType(Type::getAtomicStringFromLiteral('0')); - } elseif (get_class($string_atomic_type) === TNonEmptyNonspecificLiteralString::class) { + } elseif ($string_atomic_type::class === TNonEmptyNonspecificLiteralString::class) { $existing_var_type->removeType('string'); $existing_var_type->addType(Type::getAtomicStringFromLiteral('0')); } diff --git a/src/Psalm/Internal/Type/TemplateBound.php b/src/Psalm/Internal/Type/TemplateBound.php index b67c79cc211..1e827651ebc 100644 --- a/src/Psalm/Internal/Type/TemplateBound.php +++ b/src/Psalm/Internal/Type/TemplateBound.php @@ -11,38 +11,26 @@ */ final class TemplateBound { - public Union $type; - - /** - * This is the depth at which the template appears in a given type. - * - * In the type Foo>> the type T appears at three different depths. - * - * The shallowest-appearance of the template takes prominence when inferring the type of T. - */ - public int $appearance_depth; - - /** - * The argument offset where this template was set - * - * In the type Foo the type appears at argument offsets 0 and 2 - */ - public ?int $arg_offset = null; - - /** - * When non-null, indicates an equality template bound (vs a lower or upper bound) - */ - public ?string $equality_bound_classlike = null; - public function __construct( - Union $type, - int $appearance_depth = 0, - ?int $arg_offset = null, - ?string $equality_bound_classlike = null, + public Union $type, + /** + * This is the depth at which the template appears in a given type. + * + * In the type Foo>> the type T appears at three different depths. + * + * The shallowest-appearance of the template takes prominence when inferring the type of T. + */ + public int $appearance_depth = 0, + /** + * The argument offset where this template was set + * + * In the type Foo the type appears at argument offsets 0 and 2 + */ + public ?int $arg_offset = null, + /** + * When non-null, indicates an equality template bound (vs a lower or upper bound) + */ + public ?string $equality_bound_classlike = null, ) { - $this->type = $type; - $this->appearance_depth = $appearance_depth; - $this->arg_offset = $arg_offset; - $this->equality_bound_classlike = $equality_bound_classlike; } } diff --git a/src/Psalm/Internal/Type/TemplateInferredTypeReplacer.php b/src/Psalm/Internal/Type/TemplateInferredTypeReplacer.php index 3a872cefec1..4f3c192e919 100644 --- a/src/Psalm/Internal/Type/TemplateInferredTypeReplacer.php +++ b/src/Psalm/Internal/Type/TemplateInferredTypeReplacer.php @@ -36,7 +36,7 @@ use function array_shift; use function array_values; use function assert; -use function strpos; +use function str_starts_with; /** * @internal @@ -229,7 +229,7 @@ public static function replace( )->freeze(); } - $atomic_types = array_merge($types, $new_types); + $atomic_types = [...$types, ...$new_types]; if (!$atomic_types) { throw new UnexpectedValueException('This array should be full'); } @@ -298,7 +298,7 @@ private static function replaceTemplateParam( } elseif ($codebase) { foreach ($inferred_lower_bounds as $template_type_map) { foreach ($template_type_map as $template_class => $_) { - if (strpos($template_class, 'fn-') === 0) { + if (str_starts_with($template_class, 'fn-')) { continue; } @@ -323,7 +323,7 @@ private static function replaceTemplateParam( } } } - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { } } } diff --git a/src/Psalm/Internal/Type/TemplateResult.php b/src/Psalm/Internal/Type/TemplateResult.php index 1ad9dc2399f..31663158288 100644 --- a/src/Psalm/Internal/Type/TemplateResult.php +++ b/src/Psalm/Internal/Type/TemplateResult.php @@ -6,7 +6,6 @@ use Psalm\Type\Union; -use function array_merge; use function array_replace_recursive; /** @@ -28,15 +27,10 @@ */ final class TemplateResult { - /** - * @var array> - */ - public array $template_types; - /** * @var array>> */ - public array $lower_bounds; + public array $lower_bounds = []; /** * @var array> @@ -57,11 +51,8 @@ final class TemplateResult * @param array> $template_types * @param array> $lower_bounds */ - public function __construct(array $template_types, array $lower_bounds) + public function __construct(public array $template_types, array $lower_bounds) { - $this->template_types = $template_types; - $this->lower_bounds = []; - foreach ($lower_bounds as $key1 => $boundSet) { foreach ($boundSet as $key2 => $bound) { $this->lower_bounds[$key1][$key2] = [new TemplateBound($bound)]; @@ -79,7 +70,7 @@ public function merge(TemplateResult $result): TemplateResult /** @var array>> $lower_bounds */ $lower_bounds = array_replace_recursive($instance->lower_bounds, $result->lower_bounds); $instance->lower_bounds = $lower_bounds; - $instance->template_types = array_merge($instance->template_types, $result->template_types); + $instance->template_types = [...$instance->template_types, ...$result->template_types]; return $instance; } diff --git a/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php b/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php index cc6281b151b..fca39e97927 100644 --- a/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php +++ b/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php @@ -46,6 +46,7 @@ use function count; use function in_array; use function reset; +use function str_starts_with; use function strpos; use function strtolower; use function substr; @@ -505,7 +506,7 @@ private static function findMatchingAtomicTypesForTemplate( continue; } - if (strpos($input_key, $key . '&') === 0) { + if (str_starts_with($input_key, $key . '&')) { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } @@ -530,7 +531,7 @@ private static function findMatchingAtomicTypesForTemplate( $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // do nothing } } @@ -592,7 +593,7 @@ private static function findMatchingAtomicTypesForTemplate( $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // do nothing } } diff --git a/src/Psalm/Internal/Type/TypeAlias/ClassTypeAlias.php b/src/Psalm/Internal/Type/TypeAlias/ClassTypeAlias.php index 945fbc0f103..d9b247ca687 100644 --- a/src/Psalm/Internal/Type/TypeAlias/ClassTypeAlias.php +++ b/src/Psalm/Internal/Type/TypeAlias/ClassTypeAlias.php @@ -12,16 +12,10 @@ */ final class ClassTypeAlias implements TypeAlias { - /** - * @var list - */ - public array $replacement_atomic_types; - /** * @param list $replacement_atomic_types */ - public function __construct(array $replacement_atomic_types) + public function __construct(public array $replacement_atomic_types) { - $this->replacement_atomic_types = $replacement_atomic_types; } } diff --git a/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php b/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php index 35d6893ee96..1571956ee6e 100644 --- a/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php +++ b/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php @@ -15,16 +15,10 @@ final class InlineTypeAlias implements TypeAlias { use ImmutableNonCloneableTrait; - /** - * @var list - */ - public array $replacement_tokens; - /** * @param list $replacement_tokens */ - public function __construct(array $replacement_tokens) + public function __construct(public array $replacement_tokens) { - $this->replacement_tokens = $replacement_tokens; } } diff --git a/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php b/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php index c8bfacbf0d4..9ccc65ae323 100644 --- a/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php +++ b/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php @@ -15,27 +15,7 @@ final class LinkableTypeAlias implements TypeAlias { use ImmutableNonCloneableTrait; - public string $declaring_fq_classlike_name; - - public string $alias_name; - - public int $line_number; - - public int $start_offset; - - public int $end_offset; - - public function __construct( - string $declaring_fq_classlike_name, - string $alias_name, - int $line_number, - int $start_offset, - int $end_offset, - ) { - $this->declaring_fq_classlike_name = $declaring_fq_classlike_name; - $this->alias_name = $alias_name; - $this->line_number = $line_number; - $this->start_offset = $start_offset; - $this->end_offset = $end_offset; + public function __construct(public string $declaring_fq_classlike_name, public string $alias_name, public int $line_number, public int $start_offset, public int $end_offset) + { } } diff --git a/src/Psalm/Internal/Type/TypeCombiner.php b/src/Psalm/Internal/Type/TypeCombiner.php index 7bad564408c..51edb33080c 100644 --- a/src/Psalm/Internal/Type/TypeCombiner.php +++ b/src/Psalm/Internal/Type/TypeCombiner.php @@ -63,7 +63,6 @@ use function array_values; use function assert; use function count; -use function get_class; use function is_int; use function is_numeric; use function min; @@ -289,7 +288,7 @@ public static function combine( } $has_non_specific_string = isset($combination->value_types['string']) - && get_class($combination->value_types['string']) === TString::class; + && $combination->value_types['string']::class === TString::class; if (!$has_non_specific_string) { $object_type = self::combine( @@ -439,11 +438,11 @@ private static function scrapeTypeProperties( return null; } - if (get_class($type) === TBool::class && isset($combination->value_types['false'])) { + if ($type::class === TBool::class && isset($combination->value_types['false'])) { unset($combination->value_types['false']); } - if (get_class($type) === TBool::class && isset($combination->value_types['true'])) { + if ($type::class === TBool::class && isset($combination->value_types['true'])) { unset($combination->value_types['true']); } @@ -1105,52 +1104,52 @@ private static function scrapeStringProperties( } else { $combination->value_types[$type_key] = $type; } - } elseif (get_class($combination->value_types['string']) !== TString::class) { - if (get_class($type) === TString::class) { + } elseif ($combination->value_types['string']::class !== TString::class) { + if ($type::class === TString::class) { $combination->value_types['string'] = $type; - } elseif (get_class($combination->value_types['string']) !== get_class($type)) { - if (get_class($type) === TNonEmptyString::class - && get_class($combination->value_types['string']) === TNumericString::class + } elseif ($combination->value_types['string']::class !== $type::class) { + if ($type::class === TNonEmptyString::class + && $combination->value_types['string']::class === TNumericString::class ) { $combination->value_types['string'] = $type; - } elseif (get_class($type) === TNumericString::class - && get_class($combination->value_types['string']) === TNonEmptyString::class + } elseif ($type::class === TNumericString::class + && $combination->value_types['string']::class === TNonEmptyString::class ) { // do nothing - } elseif ((get_class($type) === TNonEmptyString::class - || get_class($type) === TNumericString::class) - && get_class($combination->value_types['string']) === TNonFalsyString::class + } elseif (($type::class === TNonEmptyString::class + || $type::class === TNumericString::class) + && $combination->value_types['string']::class === TNonFalsyString::class ) { $combination->value_types['string'] = $type; - } elseif (get_class($type) === TNonFalsyString::class - && (get_class($combination->value_types['string']) === TNonEmptyString::class - || get_class($combination->value_types['string']) === TNumericString::class) + } elseif ($type::class === TNonFalsyString::class + && ($combination->value_types['string']::class === TNonEmptyString::class + || $combination->value_types['string']::class === TNumericString::class) ) { // do nothing - } elseif ((get_class($type) === TNonEmptyString::class - || get_class($type) === TNonFalsyString::class) - && get_class($combination->value_types['string']) === TNonEmptyLowercaseString::class + } elseif (($type::class === TNonEmptyString::class + || $type::class === TNonFalsyString::class) + && $combination->value_types['string']::class === TNonEmptyLowercaseString::class ) { $combination->value_types['string'] = new TNonEmptyString(); - } elseif ((get_class($combination->value_types['string']) === TNonEmptyString::class - || get_class($combination->value_types['string']) === TNonFalsyString::class) - && get_class($type) === TNonEmptyLowercaseString::class + } elseif (($combination->value_types['string']::class === TNonEmptyString::class + || $combination->value_types['string']::class === TNonFalsyString::class) + && $type::class === TNonEmptyLowercaseString::class ) { $combination->value_types['string'] = new TNonEmptyString(); - } elseif (get_class($type) === TLowercaseString::class - && get_class($combination->value_types['string']) === TNonEmptyLowercaseString::class + } elseif ($type::class === TLowercaseString::class + && $combination->value_types['string']::class === TNonEmptyLowercaseString::class ) { $combination->value_types['string'] = $type; - } elseif (get_class($combination->value_types['string']) === TLowercaseString::class - && get_class($type) === TNonEmptyLowercaseString::class + } elseif ($combination->value_types['string']::class === TLowercaseString::class + && $type::class === TNonEmptyLowercaseString::class ) { //no-change - } elseif (get_class($combination->value_types['string']) + } elseif ($combination->value_types['string']::class === TNonEmptyNonspecificLiteralString::class && $type instanceof TNonEmptyString ) { $combination->value_types['string'] = new TNonEmptyString(); - } elseif (get_class($type) === TNonEmptyNonspecificLiteralString::class + } elseif ($type::class === TNonEmptyNonspecificLiteralString::class && $combination->value_types['string'] instanceof TNonEmptyString ) { // do nothing @@ -1226,8 +1225,8 @@ private static function scrapeIntProperties( if ($combination->ints || !isset($combination->value_types['int'])) { $combination->value_types['int'] = $type; } elseif (isset($combination->value_types['int']) - && get_class($combination->value_types['int']) - !== get_class($type) + && $combination->value_types['int']::class + !== $type::class ) { $combination->value_types['int'] = new TInt(); } @@ -1309,7 +1308,7 @@ private static function getClassLikes(Codebase $codebase, string $fq_classlike_n { try { $class_storage = $codebase->classlike_storage_provider->get($fq_classlike_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return []; } diff --git a/src/Psalm/Internal/Type/TypeExpander.php b/src/Psalm/Internal/Type/TypeExpander.php index d4037652e8b..57c7a1eef61 100644 --- a/src/Psalm/Internal/Type/TypeExpander.php +++ b/src/Psalm/Internal/Type/TypeExpander.php @@ -44,7 +44,6 @@ use function array_merge; use function array_values; use function count; -use function get_class; use function is_string; use function reset; use function strtolower; @@ -156,10 +155,7 @@ public static function expandAtomic( ); if ($extra_type instanceof TNamedObject && $extra_type->extra_types) { - $new_intersection_types = array_merge( - $new_intersection_types, - $extra_type->extra_types, - ); + $new_intersection_types = [...$new_intersection_types, ...$extra_type->extra_types]; $extra_type = $extra_type->setIntersectionTypes([]); } $extra_types[$extra_type->getKey()] = $extra_type; @@ -254,7 +250,7 @@ public static function expandAtomic( $return_type->const_name, ReflectionProperty::IS_PRIVATE, ); - } catch (CircularReferenceException $e) { + } catch (CircularReferenceException) { $class_constant = null; } @@ -615,7 +611,7 @@ private static function expandNamedObject( bool &$expand_generic = false, ): TNamedObject|TTemplateParam { if ($expand_generic - && get_class($return_type) === TNamedObject::class + && $return_type::class === TNamedObject::class && !$return_type->extra_types && $codebase->classOrInterfaceExists($return_type->value) ) { @@ -1065,7 +1061,7 @@ private static function expandKeyOfValueOf( false, $return_type instanceof TValueOf, ); - } catch (CircularReferenceException $e) { + } catch (CircularReferenceException) { return [$return_type]; } diff --git a/src/Psalm/Internal/Type/TypeParser.php b/src/Psalm/Internal/Type/TypeParser.php index eda058b9b55..f12029cafcb 100644 --- a/src/Psalm/Internal/Type/TypeParser.php +++ b/src/Psalm/Internal/Type/TypeParser.php @@ -85,13 +85,14 @@ use function defined; use function end; use function explode; -use function get_class; use function in_array; use function is_int; use function is_numeric; use function preg_match; use function preg_replace; use function reset; +use function str_contains; +use function str_starts_with; use function stripslashes; use function strlen; use function strpos; @@ -125,8 +126,8 @@ public static function parseTokens( // Note: valid identifiers can include class names or $this if (!preg_match('@^(\$this|\\\\?[a-zA-Z_\x7f-\xff][\\\\\-0-9a-zA-Z_\x7f-\xff]*)$@', $only_token[0])) { if (!is_numeric($only_token[0]) - && strpos($only_token[0], '\'') !== false - && strpos($only_token[0], '"') !== false + && str_contains($only_token[0], '\'') + && str_contains($only_token[0], '"') ) { throw new TypeParseTreeException("Invalid type '$only_token[0]'"); } @@ -394,7 +395,7 @@ public static function getTypeFromTree( } if (!$parse_tree instanceof Value) { - throw new InvalidArgumentException('Unrecognised parse tree type ' . get_class($parse_tree)); + throw new InvalidArgumentException('Unrecognised parse tree type ' . $parse_tree::class); } if ($parse_tree->value[0] === '"' || $parse_tree->value[0] === '\'') { @@ -903,7 +904,7 @@ private static function getTypeFromGenericTree( if (!$atomic_type instanceof TLiteralInt && !($atomic_type instanceof TClassConstant - && strpos($atomic_type->const_name, '*') === false) + && !str_contains($atomic_type->const_name, '*')) ) { throw new TypeParseTreeException( 'int-mask types must all be integer values or scalar class constants', @@ -943,7 +944,7 @@ private static function getTypeFromGenericTree( 'Invalid reference passed to int-mask-of', ); } elseif ($param_type instanceof TClassConstant - && strpos($param_type->const_name, '*') === false + && !str_contains($param_type->const_name, '*') ) { throw new TypeParseTreeException( 'Class constant passed to int-mask-of must be a wildcard type', @@ -1258,7 +1259,7 @@ private static function getTypeFromCallableTree( $params[] = $param; } - $pure = strpos($parse_tree->value, 'pure-') === 0 ? true : null; + $pure = str_starts_with($parse_tree->value, 'pure-') ? true : null; if (in_array(strtolower($parse_tree->value), ['closure', '\closure', 'pure-closure'], true)) { return new TClosure('Closure', $params, null, $pure, [], [], $from_docblock); @@ -1309,7 +1310,7 @@ private static function getTypeFromIndexAccessTree( $array_defining_class = array_keys($template_type_map[$array_param_name])[0]; if ($offset_defining_class !== $array_defining_class - && strpos($offset_defining_class, 'fn-') !== 0 + && !str_starts_with($offset_defining_class, 'fn-') ) { throw new TypeParseTreeException('Template params are defined in different locations'); } @@ -1456,7 +1457,7 @@ private static function getTypeFromKeyedArrayTree( return new TObjectWithProperties($properties, [], [], $from_docblock); } - $callable = strpos($type, 'callable-') === 0; + $callable = str_starts_with($type, 'callable-'); $class = TKeyedArray::class; if ($callable) { $class = TCallableKeyedArray::class; @@ -1569,7 +1570,7 @@ private static function extractKeyedIntersectionTypes( continue; } - if (get_class($intersection_type) === TObject::class) { + if ($intersection_type::class === TObject::class) { continue; } @@ -1585,7 +1586,7 @@ private static function extractKeyedIntersectionTypes( throw new TypeParseTreeException( 'Intersection types must be all objects, ' - . get_class($intersection_type) . ' provided', + . $intersection_type::class . ' provided', ); } diff --git a/src/Psalm/Internal/Type/TypeTokenizer.php b/src/Psalm/Internal/Type/TypeTokenizer.php index a772bc7503e..0a647028608 100644 --- a/src/Psalm/Internal/Type/TypeTokenizer.php +++ b/src/Psalm/Internal/Type/TypeTokenizer.php @@ -317,37 +317,15 @@ public static function fixScalarTerms( ?int $analysis_php_version_id = null, ): string { $type_string_lc = strtolower($type_string); - - switch ($type_string_lc) { - case 'int': - case 'void': - case 'float': - case 'string': - case 'bool': - case 'callable': - case 'iterable': - case 'array': - case 'object': - case 'true': - case 'false': - case 'null': - case 'mixed': - return $type_string_lc; - } - - switch ($type_string) { - case 'boolean': - return $analysis_php_version_id !== null ? $type_string : 'bool'; - - case 'integer': - return $analysis_php_version_id !== null ? $type_string : 'int'; - - case 'double': - case 'real': - return $analysis_php_version_id !== null ? $type_string : 'float'; - } - - return $type_string; + return match ($type_string_lc) { + 'int', 'void', 'float', 'string', 'bool', 'callable', 'iterable', 'array', 'object', 'true', 'false', 'null', 'mixed' => $type_string_lc, + default => match ($type_string) { + 'boolean' => $analysis_php_version_id !== null ? $type_string : 'bool', + 'integer' => $analysis_php_version_id !== null ? $type_string : 'int', + 'double', 'real' => $analysis_php_version_id !== null ? $type_string : 'float', + default => $type_string, + }, + }; } /** diff --git a/src/Psalm/Internal/TypeVisitor/CanContainObjectTypeVisitor.php b/src/Psalm/Internal/TypeVisitor/CanContainObjectTypeVisitor.php index 833f6d3e4bf..dca8271b55a 100644 --- a/src/Psalm/Internal/TypeVisitor/CanContainObjectTypeVisitor.php +++ b/src/Psalm/Internal/TypeVisitor/CanContainObjectTypeVisitor.php @@ -16,11 +16,8 @@ final class CanContainObjectTypeVisitor extends TypeVisitor { private bool $contains_object_type = false; - private Codebase $codebase; - - public function __construct(Codebase $codebase) + public function __construct(private readonly Codebase $codebase) { - $this->codebase = $codebase; } protected function enterNode(TypeNode $type): ?int diff --git a/src/Psalm/Internal/TypeVisitor/ClasslikeReplacer.php b/src/Psalm/Internal/TypeVisitor/ClasslikeReplacer.php index e46d68c45e2..5ae357812d8 100644 --- a/src/Psalm/Internal/TypeVisitor/ClasslikeReplacer.php +++ b/src/Psalm/Internal/TypeVisitor/ClasslikeReplacer.php @@ -18,15 +18,13 @@ */ final class ClasslikeReplacer extends MutableTypeVisitor { - private string $old; - private string $new; + private readonly string $old; public function __construct( string $old, - string $new, + private readonly string $new, ) { $this->old = strtolower($old); - $this->new = $new; } protected function enterNode(TypeNode &$type): ?int diff --git a/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php b/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php index 4fc9df15929..6bad2c78a25 100644 --- a/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php +++ b/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php @@ -17,20 +17,14 @@ */ final class ContainsClassLikeVisitor extends TypeVisitor { - /** - * @var lowercase-string - */ - private string $fq_classlike_name; - private bool $contains_classlike = false; /** * @psalm-external-mutation-free * @param lowercase-string $fq_classlike_name */ - public function __construct(string $fq_classlike_name) + public function __construct(private readonly string $fq_classlike_name) { - $this->fq_classlike_name = $fq_classlike_name; } /** diff --git a/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php b/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php index b7e8720bedd..22e290ac01e 100644 --- a/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php +++ b/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php @@ -16,10 +16,8 @@ */ final class FromDocblockSetter extends MutableTypeVisitor { - private bool $from_docblock; - public function __construct(bool $from_docblock) + public function __construct(private readonly bool $from_docblock) { - $this->from_docblock = $from_docblock; } /** * @return self::STOP_TRAVERSAL|self::DONT_TRAVERSE_CHILDREN|null diff --git a/src/Psalm/Internal/TypeVisitor/TypeChecker.php b/src/Psalm/Internal/TypeVisitor/TypeChecker.php index f05faa9a05c..34abe6bc798 100644 --- a/src/Psalm/Internal/TypeVisitor/TypeChecker.php +++ b/src/Psalm/Internal/TypeVisitor/TypeChecker.php @@ -38,7 +38,8 @@ use function array_search; use function count; use function md5; -use function strpos; +use function str_contains; +use function str_starts_with; use function strtolower; /** @@ -46,52 +47,14 @@ */ final class TypeChecker extends TypeVisitor { - private StatementsSource $source; - - private CodeLocation $code_location; - - /** - * @var array - */ - private array $suppressed_issues; - - /** - * @var array - */ - private array $phantom_classes; - - private bool $inferred; - - private bool $inherited; - - private bool $prevent_template_covariance; - private bool $has_errors = false; - private ?string $calling_method_id = null; - /** * @param array $suppressed_issues * @param array $phantom_classes */ - public function __construct( - StatementsSource $source, - CodeLocation $code_location, - array $suppressed_issues, - array $phantom_classes = [], - bool $inferred = true, - bool $inherited = false, - bool $prevent_template_covariance = false, - ?string $calling_method_id = null, - ) { - $this->source = $source; - $this->code_location = $code_location; - $this->suppressed_issues = $suppressed_issues; - $this->phantom_classes = $phantom_classes; - $this->inferred = $inferred; - $this->inherited = $inherited; - $this->prevent_template_covariance = $prevent_template_covariance; - $this->calling_method_id = $calling_method_id; + public function __construct(private readonly StatementsSource $source, private readonly CodeLocation $code_location, private readonly array $suppressed_issues, private array $phantom_classes = [], private readonly bool $inferred = true, private readonly bool $inherited = false, private bool $prevent_template_covariance = false, private readonly ?string $calling_method_id = null) + { } /** @@ -212,7 +175,7 @@ private function checkGenericParams(TGenericObject $atomic): void try { $class_storage = $codebase->classlike_storage_provider->get(strtolower($atomic->value)); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { return; } @@ -312,7 +275,7 @@ public function checkScalarClassConstant(TClassConstant $atomic): void } $const_name = $atomic->const_name; - if (strpos($const_name, '*') !== false) { + if (str_contains($const_name, '*')) { TypeExpander::expandAtomic( $this->source->getCodebase(), $atomic, @@ -349,7 +312,7 @@ public function checkScalarClassConstant(TClassConstant $atomic): void public function checkTemplateParam(TTemplateParam $atomic): void { if ($this->prevent_template_covariance - && strpos($atomic->defining_class, 'fn-') !== 0 + && !str_starts_with($atomic->defining_class, 'fn-') && $atomic->defining_class !== 'class-string-map' ) { $codebase = $this->source->getCodebase(); diff --git a/src/Psalm/Internal/TypeVisitor/TypeLocalizer.php b/src/Psalm/Internal/TypeVisitor/TypeLocalizer.php index 17a710d8821..57ec6d184e8 100644 --- a/src/Psalm/Internal/TypeVisitor/TypeLocalizer.php +++ b/src/Psalm/Internal/TypeVisitor/TypeLocalizer.php @@ -21,21 +21,11 @@ */ final class TypeLocalizer extends MutableTypeVisitor { - /** - * @var array> - */ - private array $extends; - private string $base_fq_class_name; - /** * @param array> $extends */ - public function __construct( - array $extends, - string $base_fq_class_name, - ) { - $this->extends = $extends; - $this->base_fq_class_name = $base_fq_class_name; + public function __construct(private array $extends, private readonly string $base_fq_class_name) + { } protected function enterNode(TypeNode &$type): ?int diff --git a/src/Psalm/Internal/TypeVisitor/TypeScanner.php b/src/Psalm/Internal/TypeVisitor/TypeScanner.php index e610f249d0b..0a99eab7412 100644 --- a/src/Psalm/Internal/TypeVisitor/TypeScanner.php +++ b/src/Psalm/Internal/TypeVisitor/TypeScanner.php @@ -19,26 +19,11 @@ */ final class TypeScanner extends TypeVisitor { - private Scanner $scanner; - - private ?FileStorage $file_storage = null; - - /** - * @var array - */ - private array $phantom_classes; - /** * @param array $phantom_classes */ - public function __construct( - Scanner $scanner, - ?FileStorage $file_storage, - array $phantom_classes, - ) { - $this->scanner = $scanner; - $this->file_storage = $file_storage; - $this->phantom_classes = $phantom_classes; + public function __construct(private readonly Scanner $scanner, private readonly ?FileStorage $file_storage, private array $phantom_classes) + { } protected function enterNode(TypeNode $type): ?int diff --git a/src/Psalm/Internal/VersionUtils.php b/src/Psalm/Internal/VersionUtils.php index 72e8be62720..fcf7f279f86 100644 --- a/src/Psalm/Internal/VersionUtils.php +++ b/src/Psalm/Internal/VersionUtils.php @@ -94,7 +94,7 @@ private static function loadComposerVersions(): ?array self::PSALM_PACKAGE => self::getVersion(self::PSALM_PACKAGE), self::PHP_PARSER_PACKAGE => self::getVersion(self::PHP_PARSER_PACKAGE), ]; - } catch (OutOfBoundsException $ex) { + } catch (OutOfBoundsException) { } return null; } diff --git a/src/Psalm/Issue/ClassConstantIssue.php b/src/Psalm/Issue/ClassConstantIssue.php index cb6dac913cd..0527f6c20e0 100644 --- a/src/Psalm/Issue/ClassConstantIssue.php +++ b/src/Psalm/Issue/ClassConstantIssue.php @@ -8,14 +8,11 @@ abstract class ClassConstantIssue extends CodeIssue { - public string $const_id; - public function __construct( string $message, CodeLocation $code_location, - string $const_id, + public string $const_id, ) { parent::__construct($message, $code_location); - $this->const_id = $const_id; } } diff --git a/src/Psalm/Issue/ClassIssue.php b/src/Psalm/Issue/ClassIssue.php index 959f625cf42..d88d50d5178 100644 --- a/src/Psalm/Issue/ClassIssue.php +++ b/src/Psalm/Issue/ClassIssue.php @@ -8,14 +8,11 @@ abstract class ClassIssue extends CodeIssue { - public string $fq_classlike_name; - public function __construct( string $message, CodeLocation $code_location, - string $fq_classlike_name, + public string $fq_classlike_name, ) { parent::__construct($message, $code_location); - $this->fq_classlike_name = $fq_classlike_name; } } diff --git a/src/Psalm/Issue/CodeIssue.php b/src/Psalm/Issue/CodeIssue.php index e4b7791caa1..a5127b3cfef 100644 --- a/src/Psalm/Issue/CodeIssue.php +++ b/src/Psalm/Issue/CodeIssue.php @@ -17,24 +17,18 @@ abstract class CodeIssue /** @var int<0, max> */ public const SHORTCODE = 0; - /** - * @readonly - */ - public CodeLocation $code_location; - - /** - * @readonly - */ - public string $message; - public ?string $dupe_key = null; public function __construct( - string $message, - CodeLocation $code_location, + /** + * @readonly + */ + public string $message, + /** + * @readonly + */ + public CodeLocation $code_location, ) { - $this->code_location = $code_location; - $this->message = $message; } public function getShortLocationWithPrevious(): string diff --git a/src/Psalm/Issue/InvalidInterfaceImplementation.php b/src/Psalm/Issue/InvalidInterfaceImplementation.php index 4993a72e4e9..1acfa745e1f 100644 --- a/src/Psalm/Issue/InvalidInterfaceImplementation.php +++ b/src/Psalm/Issue/InvalidInterfaceImplementation.php @@ -6,6 +6,6 @@ class InvalidInterfaceImplementation extends ClassIssue { - const ERROR_LEVEL = -1; - const SHORTCODE = 317; + final public const ERROR_LEVEL = -1; + final public const SHORTCODE = 317; } diff --git a/src/Psalm/Issue/PrivateFinalMethod.php b/src/Psalm/Issue/PrivateFinalMethod.php index 8884c29ad0a..1df8c8421a0 100644 --- a/src/Psalm/Issue/PrivateFinalMethod.php +++ b/src/Psalm/Issue/PrivateFinalMethod.php @@ -6,6 +6,6 @@ class PrivateFinalMethod extends MethodIssue { - public const ERROR_LEVEL = 2; - public const SHORTCODE = 320; + final public const ERROR_LEVEL = 2; + final public const SHORTCODE = 320; } diff --git a/src/Psalm/Issue/PropertyIssue.php b/src/Psalm/Issue/PropertyIssue.php index 6be211689e7..9e1a24d3eff 100644 --- a/src/Psalm/Issue/PropertyIssue.php +++ b/src/Psalm/Issue/PropertyIssue.php @@ -8,14 +8,11 @@ abstract class PropertyIssue extends CodeIssue { - public string $property_id; - public function __construct( string $message, CodeLocation $code_location, - string $property_id, + public string $property_id, ) { parent::__construct($message, $code_location); - $this->property_id = $property_id; } } diff --git a/src/Psalm/Issue/RiskyCast.php b/src/Psalm/Issue/RiskyCast.php index ea267cafdc0..6f58ecdcf2e 100644 --- a/src/Psalm/Issue/RiskyCast.php +++ b/src/Psalm/Issue/RiskyCast.php @@ -6,6 +6,6 @@ class RiskyCast extends CodeIssue { - public const ERROR_LEVEL = 3; - public const SHORTCODE = 313; + final public const ERROR_LEVEL = 3; + final public const SHORTCODE = 313; } diff --git a/src/Psalm/Issue/TaintedInput.php b/src/Psalm/Issue/TaintedInput.php index f394c24ac95..b09361eab05 100644 --- a/src/Psalm/Issue/TaintedInput.php +++ b/src/Psalm/Issue/TaintedInput.php @@ -13,30 +13,22 @@ abstract class TaintedInput extends CodeIssue /** @var int<0, max> */ public const SHORTCODE = 205; - /** - * @readonly - */ - public string $journey_text; - - /** - * @var list - * @readonly - */ - public array $journey = []; - /** * @param list $journey */ public function __construct( string $message, CodeLocation $code_location, - array $journey, - string $journey_text, + /** + * @readonly + */ + public array $journey, + /** + * @readonly + */ + public string $journey_text, ) { parent::__construct($message, $code_location); - - $this->journey = $journey; - $this->journey_text = $journey_text; } /** diff --git a/src/Psalm/Issue/UnusedBaselineEntry.php b/src/Psalm/Issue/UnusedBaselineEntry.php index 7397a33d3f3..266ec1e8b4c 100644 --- a/src/Psalm/Issue/UnusedBaselineEntry.php +++ b/src/Psalm/Issue/UnusedBaselineEntry.php @@ -6,6 +6,6 @@ class UnusedBaselineEntry extends ClassIssue { - public const ERROR_LEVEL = -1; - public const SHORTCODE = 316; + final public const ERROR_LEVEL = -1; + final public const SHORTCODE = 316; } diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index fc04545fbea..8008513c792 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -55,7 +55,6 @@ use function explode; use function file_put_contents; use function fwrite; -use function get_class; use function implode; use function in_array; use function is_dir; @@ -73,8 +72,8 @@ use function sprintf; use function str_repeat; use function str_replace; +use function str_starts_with; use function strlen; -use function strpos; use function trim; use function usort; @@ -153,7 +152,7 @@ public static function maybeAdd(CodeIssue $e, array $suppressed_issues = [], boo */ public static function addUnusedSuppression(string $file_path, int $offset, string $issue_type): void { - if (strpos($issue_type, 'Tainted') === 0) { + if (str_starts_with($issue_type, 'Tainted')) { return; } @@ -180,7 +179,7 @@ public static function isSuppressed(CodeIssue $e, array $suppressed_issues = []) { $config = Config::getInstance(); - $fqcn_parts = explode('\\', get_class($e)); + $fqcn_parts = explode('\\', $e::class); $issue_type = array_pop($fqcn_parts); $file_path = $e->getFilePath(); @@ -261,14 +260,14 @@ public static function add(CodeIssue $e, bool $is_fixable = false): bool return false; } - $fqcn_parts = explode('\\', get_class($e)); + $fqcn_parts = explode('\\', $e::class); $issue_type = array_pop($fqcn_parts); if (!$project_analyzer->show_issues) { return false; } - $is_tainted = strpos($issue_type, 'Tainted') === 0; + $is_tainted = str_starts_with($issue_type, 'Tainted'); if ($codebase->taint_flow_graph && !$is_tainted) { return false; @@ -668,7 +667,7 @@ public static function finish( try { $source_control_info = (new GitInfoCollector())->collect(); - } catch (RuntimeException $e) { + } catch (RuntimeException) { // do nothing } @@ -858,84 +857,32 @@ public static function getOutput( $format = $report_options->format; - switch ($format) { - case Report::TYPE_COMPACT: - $output = new CompactReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_EMACS: - $output = new EmacsReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_TEXT: - $output = new TextReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_JSON: - $output = new JsonReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_BY_ISSUE_LEVEL: - $output = new ByIssueLevelAndTypeReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_JSON_SUMMARY: - $output = new JsonSummaryReport( - $normalized_data, - self::$fixable_issue_counts, - $report_options, - $mixed_expression_count, - $total_expression_count, - ); - break; - - case Report::TYPE_SONARQUBE: - $output = new SonarqubeReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_PYLINT: - $output = new PylintReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_CHECKSTYLE: - $output = new CheckstyleReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_XML: - $output = new XmlReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_JUNIT: - $output = new JunitReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_CONSOLE: - $output = new ConsoleReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_GITHUB_ACTIONS: - $output = new GithubActionsReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_PHP_STORM: - $output = new PhpStormReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_SARIF: - $output = new SarifReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_CODECLIMATE: - $output = new CodeClimateReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - case Report::TYPE_COUNT: - $output = new CountReport($normalized_data, self::$fixable_issue_counts, $report_options); - break; - - default: - throw new RuntimeException('Unexpected report format: ' . $report_options->format); - } + $output = match ($format) { + Report::TYPE_COMPACT => new CompactReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_EMACS => new EmacsReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_TEXT => new TextReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_JSON => new JsonReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_BY_ISSUE_LEVEL => new ByIssueLevelAndTypeReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_JSON_SUMMARY => new JsonSummaryReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + $mixed_expression_count, + $total_expression_count, + ), + Report::TYPE_SONARQUBE => new SonarqubeReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_PYLINT => new PylintReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_CHECKSTYLE => new CheckstyleReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_XML => new XmlReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_JUNIT => new JunitReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_CONSOLE => new ConsoleReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_GITHUB_ACTIONS => new GithubActionsReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_PHP_STORM => new PhpStormReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_SARIF => new SarifReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_CODECLIMATE => new CodeClimateReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_COUNT => new CountReport($normalized_data, self::$fixable_issue_counts, $report_options), + default => throw new RuntimeException('Unexpected report format: ' . $report_options->format), + }; return $output->create(); } diff --git a/src/Psalm/Plugin/ArgTypeInferer.php b/src/Psalm/Plugin/ArgTypeInferer.php index 0347eead24a..3bf841fce11 100644 --- a/src/Psalm/Plugin/ArgTypeInferer.php +++ b/src/Psalm/Plugin/ArgTypeInferer.php @@ -13,16 +13,11 @@ final class ArgTypeInferer { - private Context $context; - private StatementsAnalyzer $statements_analyzer; - /** * @internal */ - public function __construct(Context $context, StatementsAnalyzer $statements_analyzer) + public function __construct(private readonly Context $context, private readonly StatementsAnalyzer $statements_analyzer) { - $this->context = $context; - $this->statements_analyzer = $statements_analyzer; } public function infer(PhpParser\Node\Arg $arg): false|Union diff --git a/src/Psalm/Plugin/DynamicTemplateProvider.php b/src/Psalm/Plugin/DynamicTemplateProvider.php index fbbcb3a36fd..80a5a432409 100644 --- a/src/Psalm/Plugin/DynamicTemplateProvider.php +++ b/src/Psalm/Plugin/DynamicTemplateProvider.php @@ -10,14 +10,11 @@ final class DynamicTemplateProvider { - private string $defining_class; - /** * @internal */ - public function __construct(string $defining_class) + public function __construct(private readonly string $defining_class) { - $this->defining_class = $defining_class; } /** diff --git a/src/Psalm/Plugin/EventHandler/Event/AddRemoveTaintsEvent.php b/src/Psalm/Plugin/EventHandler/Event/AddRemoveTaintsEvent.php index b9b5567b1d5..2160228a064 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AddRemoveTaintsEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AddRemoveTaintsEvent.php @@ -11,26 +11,13 @@ final class AddRemoveTaintsEvent { - private Expr $expr; - private Context $context; - private StatementsSource $statements_source; - private Codebase $codebase; - /** * Called after an expression has been checked * * @internal */ - public function __construct( - Expr $expr, - Context $context, - StatementsSource $statements_source, - Codebase $codebase, - ) { - $this->expr = $expr; - $this->context = $context; - $this->statements_source = $statements_source; - $this->codebase = $codebase; + public function __construct(private readonly Expr $expr, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase) + { } public function getExpr(): Expr diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php index 6c95a0c7394..04d4ec2b49b 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php @@ -10,30 +10,14 @@ final class AfterAnalysisEvent { - private Codebase $codebase; - /** - * @var array> where string key is a filepath - */ - private array $issues; - private array $build_info; - private ?SourceControlInfo $source_control_info; - /** * Called after analysis is complete * * @param array> $issues where string key is a filepath * @internal */ - public function __construct( - Codebase $codebase, - array $issues, - array $build_info, - ?SourceControlInfo $source_control_info = null, - ) { - $this->codebase = $codebase; - $this->issues = $issues; - $this->build_info = $build_info; - $this->source_control_info = $source_control_info; + public function __construct(private readonly Codebase $codebase, private readonly array $issues, private readonly array $build_info, private readonly ?SourceControlInfo $source_control_info = null) + { } public function getCodebase(): Codebase diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeAnalysisEvent.php index 7b627ab9ffa..aa1fe7d4499 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeAnalysisEvent.php @@ -12,33 +12,14 @@ final class AfterClassLikeAnalysisEvent { - private Node\Stmt\ClassLike $stmt; - private ClassLikeStorage $classlike_storage; - private StatementsSource $statements_source; - private Codebase $codebase; - /** - * @var FileManipulation[] - */ - private array $file_replacements; - /** * Called after a statement has been checked * * @param FileManipulation[] $file_replacements * @internal */ - public function __construct( - Node\Stmt\ClassLike $stmt, - ClassLikeStorage $classlike_storage, - StatementsSource $statements_source, - Codebase $codebase, - array $file_replacements = [], - ) { - $this->stmt = $stmt; - $this->classlike_storage = $classlike_storage; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; + public function __construct(private readonly Node\Stmt\ClassLike $stmt, private readonly ClassLikeStorage $classlike_storage, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) + { } public function getStmt(): Node\Stmt\ClassLike diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeExistenceCheckEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeExistenceCheckEvent.php index 1971f150266..eccf5ad934a 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeExistenceCheckEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeExistenceCheckEvent.php @@ -11,31 +11,12 @@ final class AfterClassLikeExistenceCheckEvent { - private string $fq_class_name; - private CodeLocation $code_location; - private StatementsSource $statements_source; - private Codebase $codebase; - /** - * @var FileManipulation[] - */ - private array $file_replacements; - /** * @param FileManipulation[] $file_replacements * @internal */ - public function __construct( - string $fq_class_name, - CodeLocation $code_location, - StatementsSource $statements_source, - Codebase $codebase, - array $file_replacements = [], - ) { - $this->fq_class_name = $fq_class_name; - $this->code_location = $code_location; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; + public function __construct(private readonly string $fq_class_name, private readonly CodeLocation $code_location, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) + { } public function getFqClassName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeVisitEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeVisitEvent.php index 709708cee26..353b0398bd0 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeVisitEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeVisitEvent.php @@ -12,31 +12,12 @@ final class AfterClassLikeVisitEvent { - private ClassLike $stmt; - private ClassLikeStorage $storage; - private FileSource $statements_source; - private Codebase $codebase; - /** - * @var FileManipulation[] - */ - private array $file_replacements; - /** * @param FileManipulation[] $file_replacements * @internal */ - public function __construct( - ClassLike $stmt, - ClassLikeStorage $storage, - FileSource $statements_source, - Codebase $codebase, - array $file_replacements = [], - ) { - $this->stmt = $stmt; - $this->storage = $storage; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; + public function __construct(private readonly ClassLike $stmt, private readonly ClassLikeStorage $storage, private readonly FileSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) + { } public function getStmt(): ClassLike diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterCodebasePopulatedEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterCodebasePopulatedEvent.php index 6082be9a1a0..02465b295f3 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterCodebasePopulatedEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterCodebasePopulatedEvent.php @@ -8,16 +8,13 @@ final class AfterCodebasePopulatedEvent { - private Codebase $codebase; - /** * Called after codebase has been populated * * @internal */ - public function __construct(Codebase $codebase) + public function __construct(private readonly Codebase $codebase) { - $this->codebase = $codebase; } public function getCodebase(): Codebase diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterEveryFunctionCallAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterEveryFunctionCallAnalysisEvent.php index 4d8b8dc013f..a85eef0e2c0 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterEveryFunctionCallAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterEveryFunctionCallAnalysisEvent.php @@ -11,25 +11,9 @@ final class AfterEveryFunctionCallAnalysisEvent { - private FuncCall $expr; - private string $function_id; - private Context $context; - private StatementsSource $statements_source; - private Codebase $codebase; - /** @internal */ - public function __construct( - FuncCall $expr, - string $function_id, - Context $context, - StatementsSource $statements_source, - Codebase $codebase, - ) { - $this->expr = $expr; - $this->function_id = $function_id; - $this->context = $context; - $this->statements_source = $statements_source; - $this->codebase = $codebase; + public function __construct(private readonly FuncCall $expr, private readonly string $function_id, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase) + { } public function getExpr(): FuncCall diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterExpressionAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterExpressionAnalysisEvent.php index 9828b39b70a..6e9f40629f3 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterExpressionAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterExpressionAnalysisEvent.php @@ -12,33 +12,14 @@ final class AfterExpressionAnalysisEvent { - private Expr $expr; - private Context $context; - private StatementsSource $statements_source; - private Codebase $codebase; - /** - * @var FileManipulation[] - */ - private array $file_replacements; - /** * Called after an expression has been checked * * @param FileManipulation[] $file_replacements * @internal */ - public function __construct( - Expr $expr, - Context $context, - StatementsSource $statements_source, - Codebase $codebase, - array $file_replacements = [], - ) { - $this->expr = $expr; - $this->context = $context; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; + public function __construct(private readonly Expr $expr, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) + { } public function getExpr(): Expr diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterFileAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterFileAnalysisEvent.php index da204223da5..8713053baf2 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterFileAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterFileAnalysisEvent.php @@ -12,33 +12,14 @@ final class AfterFileAnalysisEvent { - private StatementsSource $statements_source; - private Context $file_context; - private FileStorage $file_storage; - private Codebase $codebase; - /** - * @var Stmt[] - */ - private array $stmts; - /** * Called after a file has been checked * * @param array $stmts * @internal */ - public function __construct( - StatementsSource $statements_source, - Context $file_context, - FileStorage $file_storage, - Codebase $codebase, - array $stmts, - ) { - $this->statements_source = $statements_source; - $this->file_context = $file_context; - $this->file_storage = $file_storage; - $this->codebase = $codebase; - $this->stmts = $stmts; + public function __construct(private readonly StatementsSource $statements_source, private readonly Context $file_context, private readonly FileStorage $file_storage, private readonly Codebase $codebase, private readonly array $stmts) + { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterFunctionCallAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterFunctionCallAnalysisEvent.php index 673ad559beb..e8c45e0ced5 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterFunctionCallAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterFunctionCallAnalysisEvent.php @@ -13,41 +13,13 @@ final class AfterFunctionCallAnalysisEvent { - private FuncCall $expr; - /** - * @var non-empty-string - */ - private string $function_id; - private Context $context; - private StatementsSource $statements_source; - private Codebase $codebase; - private Union $return_type_candidate; - /** - * @var FileManipulation[] - */ - private array $file_replacements; - /** * @param non-empty-string $function_id * @param FileManipulation[] $file_replacements * @internal */ - public function __construct( - FuncCall $expr, - string $function_id, - Context $context, - StatementsSource $statements_source, - Codebase $codebase, - Union $return_type_candidate, - array $file_replacements, - ) { - $this->expr = $expr; - $this->function_id = $function_id; - $this->context = $context; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->return_type_candidate = $return_type_candidate; - $this->file_replacements = $file_replacements; + public function __construct(private readonly FuncCall $expr, private readonly string $function_id, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private readonly Union $return_type_candidate, private array $file_replacements) + { } public function getExpr(): FuncCall diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterFunctionLikeAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterFunctionLikeAnalysisEvent.php index 6a624c22dc3..a3eaa34869f 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterFunctionLikeAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterFunctionLikeAnalysisEvent.php @@ -14,39 +14,14 @@ final class AfterFunctionLikeAnalysisEvent { - private Node\FunctionLike $stmt; - private FunctionLikeStorage $functionlike_storage; - private StatementsSource $statements_source; - private Codebase $codebase; - /** - * @var FileManipulation[] - */ - private array $file_replacements; - private NodeTypeProvider $node_type_provider; - private Context $context; - /** * Called after a statement has been checked * * @param FileManipulation[] $file_replacements * @internal */ - public function __construct( - Node\FunctionLike $stmt, - FunctionLikeStorage $functionlike_storage, - StatementsSource $statements_source, - Codebase $codebase, - array $file_replacements, - NodeTypeProvider $node_type_provider, - Context $context, - ) { - $this->stmt = $stmt; - $this->functionlike_storage = $functionlike_storage; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; - $this->node_type_provider = $node_type_provider; - $this->context = $context; + public function __construct(private readonly Node\FunctionLike $stmt, private readonly FunctionLikeStorage $functionlike_storage, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements, private readonly NodeTypeProvider $node_type_provider, private readonly Context $context) + { } public function getStmt(): Node\FunctionLike diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterMethodCallAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterMethodCallAnalysisEvent.php index 829f0dc15bc..7806ec57289 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterMethodCallAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterMethodCallAnalysisEvent.php @@ -15,44 +15,12 @@ final class AfterMethodCallAnalysisEvent { - private MethodCall|StaticCall $expr; - private string $method_id; - private string $appearing_method_id; - private string $declaring_method_id; - private Context $context; - private StatementsSource $statements_source; - private Codebase $codebase; /** - * @var FileManipulation[] - */ - private array $file_replacements; - private ?Union $return_type_candidate; - - /** - * @param MethodCall|StaticCall $expr * @param FileManipulation[] $file_replacements * @internal */ - public function __construct( - 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, - ) { - $this->expr = $expr; - $this->method_id = $method_id; - $this->appearing_method_id = $appearing_method_id; - $this->declaring_method_id = $declaring_method_id; - $this->context = $context; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; - $this->return_type_candidate = $return_type_candidate; + public function __construct(private readonly MethodCall|StaticCall $expr, private readonly string $method_id, private readonly string $appearing_method_id, private readonly string $declaring_method_id, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = [], private ?Union $return_type_candidate = null) + { } /** diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterStatementAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterStatementAnalysisEvent.php index a74edefc191..af07fbb0ba3 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterStatementAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterStatementAnalysisEvent.php @@ -12,33 +12,14 @@ final class AfterStatementAnalysisEvent { - private Stmt $stmt; - private Context $context; - private StatementsSource $statements_source; - private Codebase $codebase; - /** - * @var FileManipulation[] - */ - private array $file_replacements; - /** * Called after a statement has been checked * * @param FileManipulation[] $file_replacements * @internal */ - public function __construct( - Stmt $stmt, - Context $context, - StatementsSource $statements_source, - Codebase $codebase, - array $file_replacements = [], - ) { - $this->stmt = $stmt; - $this->context = $context; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; + public function __construct(private readonly Stmt $stmt, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) + { } public function getStmt(): Stmt diff --git a/src/Psalm/Plugin/EventHandler/Event/BeforeAddIssueEvent.php b/src/Psalm/Plugin/EventHandler/Event/BeforeAddIssueEvent.php index 9e354ed900d..3f1b9685336 100644 --- a/src/Psalm/Plugin/EventHandler/Event/BeforeAddIssueEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/BeforeAddIssueEvent.php @@ -9,16 +9,9 @@ final class BeforeAddIssueEvent { - private CodeIssue $issue; - private bool $fixable; - private Codebase $codebase; - /** @internal */ - public function __construct(CodeIssue $issue, bool $fixable, Codebase $codebase) + public function __construct(private readonly CodeIssue $issue, private readonly bool $fixable, private readonly Codebase $codebase) { - $this->issue = $issue; - $this->fixable = $fixable; - $this->codebase = $codebase; } public function getIssue(): CodeIssue diff --git a/src/Psalm/Plugin/EventHandler/Event/BeforeExpressionAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/BeforeExpressionAnalysisEvent.php index 63357ee4f7b..eb5c0d9f0f7 100644 --- a/src/Psalm/Plugin/EventHandler/Event/BeforeExpressionAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/BeforeExpressionAnalysisEvent.php @@ -12,33 +12,14 @@ final class BeforeExpressionAnalysisEvent { - private Expr $expr; - private Context $context; - private StatementsSource $statements_source; - private Codebase $codebase; - /** - * @var list - */ - private array $file_replacements; - /** * Called before an expression is checked * * @param list $file_replacements * @internal */ - public function __construct( - Expr $expr, - Context $context, - StatementsSource $statements_source, - Codebase $codebase, - array $file_replacements = [], - ) { - $this->expr = $expr; - $this->context = $context; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; + public function __construct(private readonly Expr $expr, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) + { } public function getExpr(): Expr diff --git a/src/Psalm/Plugin/EventHandler/Event/BeforeFileAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/BeforeFileAnalysisEvent.php index 0dbd4441c89..ef1f722d290 100644 --- a/src/Psalm/Plugin/EventHandler/Event/BeforeFileAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/BeforeFileAnalysisEvent.php @@ -11,26 +11,13 @@ final class BeforeFileAnalysisEvent { - private StatementsSource $statements_source; - private Context $file_context; - private FileStorage $file_storage; - private Codebase $codebase; - /** * Called before a file has been checked * * @internal */ - public function __construct( - StatementsSource $statements_source, - Context $file_context, - FileStorage $file_storage, - Codebase $codebase, - ) { - $this->statements_source = $statements_source; - $this->file_context = $file_context; - $this->file_storage = $file_storage; - $this->codebase = $codebase; + public function __construct(private readonly StatementsSource $statements_source, private readonly Context $file_context, private readonly FileStorage $file_storage, private readonly Codebase $codebase) + { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/BeforeStatementAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/BeforeStatementAnalysisEvent.php index 4a37bd1b5d8..d84d2116e2c 100644 --- a/src/Psalm/Plugin/EventHandler/Event/BeforeStatementAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/BeforeStatementAnalysisEvent.php @@ -12,33 +12,14 @@ final class BeforeStatementAnalysisEvent { - private Stmt $stmt; - private Context $context; - private StatementsSource $statements_source; - private Codebase $codebase; - /** - * @var list - */ - private array $file_replacements; - /** * Called after a statement has been checked * * @param list $file_replacements * @internal */ - public function __construct( - Stmt $stmt, - Context $context, - StatementsSource $statements_source, - Codebase $codebase, - array $file_replacements = [], - ) { - $this->stmt = $stmt; - $this->context = $context; - $this->statements_source = $statements_source; - $this->codebase = $codebase; - $this->file_replacements = $file_replacements; + public function __construct(private Stmt $stmt, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) + { } public function getStmt(): Stmt diff --git a/src/Psalm/Plugin/EventHandler/Event/DynamicFunctionStorageProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/DynamicFunctionStorageProviderEvent.php index de9fc4c17b5..f4ddf2311c0 100644 --- a/src/Psalm/Plugin/EventHandler/Event/DynamicFunctionStorageProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/DynamicFunctionStorageProviderEvent.php @@ -14,33 +14,11 @@ final class DynamicFunctionStorageProviderEvent { - private ArgTypeInferer $arg_type_inferer; - private DynamicTemplateProvider $template_provider; - private StatementsSource $statement_source; - private string $function_id; - private PhpParser\Node\Expr\FuncCall $func_call; - private Context $context; - private CodeLocation $code_location; - /** * @internal */ - public function __construct( - ArgTypeInferer $arg_type_inferer, - DynamicTemplateProvider $template_provider, - StatementsSource $statements_source, - string $function_id, - PhpParser\Node\Expr\FuncCall $func_call, - Context $context, - CodeLocation $code_location, - ) { - $this->statement_source = $statements_source; - $this->function_id = $function_id; - $this->func_call = $func_call; - $this->context = $context; - $this->code_location = $code_location; - $this->arg_type_inferer = $arg_type_inferer; - $this->template_provider = $template_provider; + public function __construct(private readonly ArgTypeInferer $arg_type_inferer, private readonly DynamicTemplateProvider $template_provider, private readonly StatementsSource $statement_source, private readonly string $function_id, private readonly PhpParser\Node\Expr\FuncCall $func_call, private readonly Context $context, private readonly CodeLocation $code_location) + { } public function getArgTypeInferer(): ArgTypeInferer diff --git a/src/Psalm/Plugin/EventHandler/Event/FunctionExistenceProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/FunctionExistenceProviderEvent.php index 87389cf2b1f..60b3a7c67fe 100644 --- a/src/Psalm/Plugin/EventHandler/Event/FunctionExistenceProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/FunctionExistenceProviderEvent.php @@ -8,9 +8,6 @@ final class FunctionExistenceProviderEvent { - private StatementsSource $statements_source; - private string $function_id; - /** * Use this hook for informing whether or not a global function exists. If you know the function does * not exist, return false. If you aren't sure if it exists or not, return null and the default analysis @@ -18,12 +15,8 @@ final class FunctionExistenceProviderEvent * * @internal */ - public function __construct( - StatementsSource $statements_source, - string $function_id, - ) { - $this->statements_source = $statements_source; - $this->function_id = $function_id; + public function __construct(private readonly StatementsSource $statements_source, private readonly string $function_id) + { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/FunctionParamsProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/FunctionParamsProviderEvent.php index a26b95a3c1a..c44eafa11bf 100644 --- a/src/Psalm/Plugin/EventHandler/Event/FunctionParamsProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/FunctionParamsProviderEvent.php @@ -11,31 +11,12 @@ final class FunctionParamsProviderEvent { - private StatementsSource $statements_source; - private string $function_id; - /** - * @var PhpParser\Node\Arg[] - */ - private array $call_args; - private ?Context $context; - private ?CodeLocation $code_location; - /** * @param list $call_args * @internal */ - public function __construct( - StatementsSource $statements_source, - string $function_id, - array $call_args, - ?Context $context = null, - ?CodeLocation $code_location = null, - ) { - $this->statements_source = $statements_source; - $this->function_id = $function_id; - $this->call_args = $call_args; - $this->context = $context; - $this->code_location = $code_location; + public function __construct(private readonly StatementsSource $statements_source, private readonly string $function_id, private readonly array $call_args, private readonly ?Context $context = null, private readonly ?CodeLocation $code_location = null) + { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/FunctionReturnTypeProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/FunctionReturnTypeProviderEvent.php index e34e333e943..10752f816eb 100644 --- a/src/Psalm/Plugin/EventHandler/Event/FunctionReturnTypeProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/FunctionReturnTypeProviderEvent.php @@ -12,15 +12,6 @@ final class FunctionReturnTypeProviderEvent { - private StatementsSource $statements_source; - /** - * @var non-empty-string - */ - private string $function_id; - private FuncCall $stmt; - private Context $context; - private CodeLocation $code_location; - /** * Use this hook for providing custom return type logic. If this plugin does not know what a function should * return but another plugin may be able to determine the type, return null. Otherwise return a mixed union type @@ -29,18 +20,8 @@ final class FunctionReturnTypeProviderEvent * @param non-empty-string $function_id * @internal */ - public function __construct( - StatementsSource $statements_source, - string $function_id, - FuncCall $stmt, - Context $context, - CodeLocation $code_location, - ) { - $this->statements_source = $statements_source; - $this->function_id = $function_id; - $this->stmt = $stmt; - $this->context = $context; - $this->code_location = $code_location; + public function __construct(private readonly StatementsSource $statements_source, private readonly string $function_id, private readonly FuncCall $stmt, private readonly Context $context, private readonly CodeLocation $code_location) + { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/MethodExistenceProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/MethodExistenceProviderEvent.php index 8c86c5e2e33..e8e8878b8bb 100644 --- a/src/Psalm/Plugin/EventHandler/Event/MethodExistenceProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/MethodExistenceProviderEvent.php @@ -9,11 +9,6 @@ final class MethodExistenceProviderEvent { - private string $fq_classlike_name; - private string $method_name_lowercase; - private ?StatementsSource $source; - private ?CodeLocation $code_location; - /** * Use this hook for informing whether or not a method exists on a given object. If you know the method does * not exist, return false. If you aren't sure if it exists or not, return null and the default analysis will @@ -21,16 +16,8 @@ final class MethodExistenceProviderEvent * * @internal */ - public function __construct( - string $fq_classlike_name, - string $method_name_lowercase, - ?StatementsSource $source = null, - ?CodeLocation $code_location = null, - ) { - $this->fq_classlike_name = $fq_classlike_name; - $this->method_name_lowercase = $method_name_lowercase; - $this->source = $source; - $this->code_location = $code_location; + public function __construct(private readonly string $fq_classlike_name, private readonly string $method_name_lowercase, private readonly ?StatementsSource $source = null, private readonly ?CodeLocation $code_location = null) + { } public function getFqClasslikeName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/MethodParamsProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/MethodParamsProviderEvent.php index babc8ffa379..e6d6f097bf6 100644 --- a/src/Psalm/Plugin/EventHandler/Event/MethodParamsProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/MethodParamsProviderEvent.php @@ -11,34 +11,12 @@ final class MethodParamsProviderEvent { - private string $fq_classlike_name; - private string $method_name_lowercase; - /** - * @var list|null - */ - private ?array $call_args; - private ?StatementsSource $statements_source; - private ?Context $context; - private ?CodeLocation $code_location; - /** * @param list $call_args * @internal */ - public function __construct( - string $fq_classlike_name, - string $method_name_lowercase, - ?array $call_args = null, - ?StatementsSource $statements_source = null, - ?Context $context = null, - ?CodeLocation $code_location = null, - ) { - $this->fq_classlike_name = $fq_classlike_name; - $this->method_name_lowercase = $method_name_lowercase; - $this->call_args = $call_args; - $this->statements_source = $statements_source; - $this->context = $context; - $this->code_location = $code_location; + public function __construct(private readonly string $fq_classlike_name, private readonly string $method_name_lowercase, private readonly ?array $call_args = null, private readonly ?StatementsSource $statements_source = null, private readonly ?Context $context = null, private readonly ?CodeLocation $code_location = null) + { } public function getFqClasslikeName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/MethodReturnTypeProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/MethodReturnTypeProviderEvent.php index e6a96aba9b3..5bad23b0ca7 100644 --- a/src/Psalm/Plugin/EventHandler/Event/MethodReturnTypeProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/MethodReturnTypeProviderEvent.php @@ -12,23 +12,6 @@ final class MethodReturnTypeProviderEvent { - private StatementsSource $source; - private string $fq_classlike_name; - /** - * @var lowercase-string - */ - private string $method_name_lowercase; - private Context $context; - private CodeLocation $code_location; - private PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $stmt; - /** @var non-empty-list|null */ - private ?array $template_type_parameters; - private ?string $called_fq_classlike_name; - /** - * @var lowercase-string|null - */ - private ?string $called_method_name_lowercase; - /** * Use this hook for providing custom return type logic. If this plugin does not know what a method should return * but another plugin may be able to determine the type, return null. Otherwise return a mixed union type if @@ -39,26 +22,8 @@ final class MethodReturnTypeProviderEvent * @param lowercase-string $called_method_name_lowercase * @internal */ - public function __construct( - StatementsSource $source, - string $fq_classlike_name, - string $method_name_lowercase, - PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $stmt, - Context $context, - CodeLocation $code_location, - ?array $template_type_parameters = null, - ?string $called_fq_classlike_name = null, - ?string $called_method_name_lowercase = null, - ) { - $this->source = $source; - $this->fq_classlike_name = $fq_classlike_name; - $this->method_name_lowercase = $method_name_lowercase; - $this->context = $context; - $this->code_location = $code_location; - $this->stmt = $stmt; - $this->template_type_parameters = $template_type_parameters; - $this->called_fq_classlike_name = $called_fq_classlike_name; - $this->called_method_name_lowercase = $called_method_name_lowercase; + public function __construct(private readonly StatementsSource $source, private readonly string $fq_classlike_name, private readonly string $method_name_lowercase, private readonly PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $stmt, private readonly Context $context, private readonly CodeLocation $code_location, private readonly ?array $template_type_parameters = null, private readonly ?string $called_fq_classlike_name = null, private readonly ?string $called_method_name_lowercase = null) + { } public function getSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/MethodVisibilityProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/MethodVisibilityProviderEvent.php index b6b46458c7a..125be232acd 100644 --- a/src/Psalm/Plugin/EventHandler/Event/MethodVisibilityProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/MethodVisibilityProviderEvent.php @@ -10,25 +10,9 @@ final class MethodVisibilityProviderEvent { - private StatementsSource $source; - private string $fq_classlike_name; - private string $method_name_lowercase; - private Context $context; - private ?CodeLocation $code_location; - /** @internal */ - public function __construct( - StatementsSource $source, - string $fq_classlike_name, - string $method_name_lowercase, - Context $context, - ?CodeLocation $code_location = null, - ) { - $this->source = $source; - $this->fq_classlike_name = $fq_classlike_name; - $this->method_name_lowercase = $method_name_lowercase; - $this->context = $context; - $this->code_location = $code_location; + public function __construct(private readonly StatementsSource $source, private readonly string $fq_classlike_name, private readonly string $method_name_lowercase, private readonly Context $context, private readonly ?CodeLocation $code_location = null) + { } public function getSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/PropertyExistenceProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/PropertyExistenceProviderEvent.php index c71b544f535..49c76a414b0 100644 --- a/src/Psalm/Plugin/EventHandler/Event/PropertyExistenceProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/PropertyExistenceProviderEvent.php @@ -10,13 +10,6 @@ final class PropertyExistenceProviderEvent { - private string $fq_classlike_name; - private string $property_name; - private bool $read_mode; - private ?StatementsSource $source; - private ?Context $context; - private ?CodeLocation $code_location; - /** * Use this hook for informing whether or not a property exists on a given object. If you know the property does * not exist, return false. If you aren't sure if it exists or not, return null and the default analysis will @@ -24,20 +17,8 @@ final class PropertyExistenceProviderEvent * * @internal */ - public function __construct( - string $fq_classlike_name, - string $property_name, - bool $read_mode, - ?StatementsSource $source = null, - ?Context $context = null, - ?CodeLocation $code_location = null, - ) { - $this->fq_classlike_name = $fq_classlike_name; - $this->property_name = $property_name; - $this->read_mode = $read_mode; - $this->source = $source; - $this->context = $context; - $this->code_location = $code_location; + public function __construct(private readonly string $fq_classlike_name, private readonly string $property_name, private readonly bool $read_mode, private readonly ?StatementsSource $source = null, private readonly ?Context $context = null, private readonly ?CodeLocation $code_location = null) + { } public function getFqClasslikeName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/PropertyTypeProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/PropertyTypeProviderEvent.php index 035ac12dc77..78ab0f9f2f3 100644 --- a/src/Psalm/Plugin/EventHandler/Event/PropertyTypeProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/PropertyTypeProviderEvent.php @@ -9,25 +9,9 @@ final class PropertyTypeProviderEvent { - private string $fq_classlike_name; - private string $property_name; - private bool $read_mode; - private ?StatementsSource $source; - private ?Context $context; - /** @internal */ - public function __construct( - string $fq_classlike_name, - string $property_name, - bool $read_mode, - ?StatementsSource $source = null, - ?Context $context = null, - ) { - $this->fq_classlike_name = $fq_classlike_name; - $this->property_name = $property_name; - $this->read_mode = $read_mode; - $this->source = $source; - $this->context = $context; + public function __construct(private readonly string $fq_classlike_name, private readonly string $property_name, private readonly bool $read_mode, private readonly ?StatementsSource $source = null, private readonly ?Context $context = null) + { } public function getFqClasslikeName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/PropertyVisibilityProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/PropertyVisibilityProviderEvent.php index eaccc482f22..b0214fb5c49 100644 --- a/src/Psalm/Plugin/EventHandler/Event/PropertyVisibilityProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/PropertyVisibilityProviderEvent.php @@ -10,28 +10,9 @@ final class PropertyVisibilityProviderEvent { - private StatementsSource $source; - private string $fq_classlike_name; - private string $property_name; - private bool $read_mode; - private Context $context; - private CodeLocation $code_location; - /** @internal */ - public function __construct( - StatementsSource $source, - string $fq_classlike_name, - string $property_name, - bool $read_mode, - Context $context, - CodeLocation $code_location, - ) { - $this->source = $source; - $this->fq_classlike_name = $fq_classlike_name; - $this->property_name = $property_name; - $this->read_mode = $read_mode; - $this->context = $context; - $this->code_location = $code_location; + public function __construct(private readonly StatementsSource $source, private readonly string $fq_classlike_name, private readonly string $property_name, private readonly bool $read_mode, private readonly Context $context, private readonly CodeLocation $code_location) + { } public function getSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/StringInterpreterEvent.php b/src/Psalm/Plugin/EventHandler/Event/StringInterpreterEvent.php index 968d955af0d..431d316142c 100644 --- a/src/Psalm/Plugin/EventHandler/Event/StringInterpreterEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/StringInterpreterEvent.php @@ -8,19 +8,14 @@ final class StringInterpreterEvent { - private string $value; - private Codebase $codebase; - /** * Called after a statement has been checked * * @psalm-external-mutation-free * @internal */ - public function __construct(string $value, Codebase $codebase) + public function __construct(private readonly string $value, private readonly Codebase $codebase) { - $this->value = $value; - $this->codebase = $codebase; } public function getValue(): string diff --git a/src/Psalm/PluginFileExtensionsSocket.php b/src/Psalm/PluginFileExtensionsSocket.php index 6c6694e3788..ae2e957fc6b 100644 --- a/src/Psalm/PluginFileExtensionsSocket.php +++ b/src/Psalm/PluginFileExtensionsSocket.php @@ -16,8 +16,6 @@ final class PluginFileExtensionsSocket implements FileExtensionsInterface { - private Config $config; - /** * @var array> */ @@ -36,9 +34,8 @@ final class PluginFileExtensionsSocket implements FileExtensionsInterface /** * @internal */ - public function __construct(Config $config) + public function __construct(private readonly Config $config) { - $this->config = $config; } /** diff --git a/src/Psalm/PluginRegistrationSocket.php b/src/Psalm/PluginRegistrationSocket.php index de44e774e4b..b91c22d34e7 100644 --- a/src/Psalm/PluginRegistrationSocket.php +++ b/src/Psalm/PluginRegistrationSocket.php @@ -23,17 +23,11 @@ final class PluginRegistrationSocket implements RegistrationInterface { - private Config $config; - - private Codebase $codebase; - /** * @internal */ - public function __construct(Config $config, Codebase $codebase) + public function __construct(private readonly Config $config, private readonly Codebase $codebase) { - $this->config = $config; - $this->codebase = $codebase; } public function addStubFile(string $file_name): void diff --git a/src/Psalm/Progress/LongProgress.php b/src/Psalm/Progress/LongProgress.php index 8cf23fa1fc6..4bfa064d8e4 100644 --- a/src/Psalm/Progress/LongProgress.php +++ b/src/Psalm/Progress/LongProgress.php @@ -15,20 +15,14 @@ class LongProgress extends Progress { - public const NUMBER_OF_COLUMNS = 60; + final public const NUMBER_OF_COLUMNS = 60; protected ?int $number_of_tasks = null; protected int $progress = 0; - protected bool $print_errors = false; - - protected bool $print_infos = false; - - public function __construct(bool $print_errors = true, bool $print_infos = true) + public function __construct(protected bool $print_errors = true, protected bool $print_infos = true) { - $this->print_errors = $print_errors; - $this->print_infos = $print_infos; } public function startScanningFiles(): void diff --git a/src/Psalm/Report.php b/src/Psalm/Report.php index c2a86945672..675f87968d3 100644 --- a/src/Psalm/Report.php +++ b/src/Psalm/Report.php @@ -15,32 +15,29 @@ abstract class Report { - public const TYPE_COMPACT = 'compact'; - public const TYPE_CONSOLE = 'console'; - public const TYPE_PYLINT = 'pylint'; - public const TYPE_JSON = 'json'; - public const TYPE_JSON_SUMMARY = 'json-summary'; - public const TYPE_SONARQUBE = 'sonarqube'; - public const TYPE_EMACS = 'emacs'; - public const TYPE_XML = 'xml'; - public const TYPE_JUNIT = 'junit'; - public const TYPE_CHECKSTYLE = 'checkstyle'; - public const TYPE_TEXT = 'text'; - public const TYPE_GITHUB_ACTIONS = 'github'; - public const TYPE_PHP_STORM = 'phpstorm'; - public const TYPE_SARIF = 'sarif'; - public const TYPE_CODECLIMATE = 'codeclimate'; - public const TYPE_COUNT = 'count'; - public const TYPE_BY_ISSUE_LEVEL = 'by-issue-level'; + final public const TYPE_COMPACT = 'compact'; + final public const TYPE_CONSOLE = 'console'; + final public const TYPE_PYLINT = 'pylint'; + final public const TYPE_JSON = 'json'; + final public const TYPE_JSON_SUMMARY = 'json-summary'; + final public const TYPE_SONARQUBE = 'sonarqube'; + final public const TYPE_EMACS = 'emacs'; + final public const TYPE_XML = 'xml'; + final public const TYPE_JUNIT = 'junit'; + final public const TYPE_CHECKSTYLE = 'checkstyle'; + final public const TYPE_TEXT = 'text'; + final public const TYPE_GITHUB_ACTIONS = 'github'; + final public const TYPE_PHP_STORM = 'phpstorm'; + final public const TYPE_SARIF = 'sarif'; + final public const TYPE_CODECLIMATE = 'codeclimate'; + final public const TYPE_COUNT = 'count'; + final public const TYPE_BY_ISSUE_LEVEL = 'by-issue-level'; /** * @var array */ protected array $issues_data; - /** @var array */ - protected array $fixable_issue_counts; - protected bool $use_color; protected bool $show_snippet; @@ -51,20 +48,16 @@ abstract class Report protected bool $in_ci; - protected int $mixed_expression_count; - - protected int $total_expression_count; - /** * @param array $issues_data * @param array $fixable_issue_counts */ public function __construct( array $issues_data, - array $fixable_issue_counts, + protected array $fixable_issue_counts, ReportOptions $report_options, - int $mixed_expression_count = 1, - int $total_expression_count = 1, + protected int $mixed_expression_count = 1, + protected int $total_expression_count = 1, ) { if (!$report_options->show_info) { $this->issues_data = array_filter( @@ -74,16 +67,12 @@ public function __construct( } else { $this->issues_data = $issues_data; } - $this->fixable_issue_counts = $fixable_issue_counts; $this->use_color = $report_options->use_color; $this->show_snippet = $report_options->show_snippet; $this->show_info = $report_options->show_info; $this->pretty = $report_options->pretty; $this->in_ci = $report_options->in_ci; - - $this->mixed_expression_count = $mixed_expression_count; - $this->total_expression_count = $total_expression_count; } protected function xmlEncode(string $data): string diff --git a/src/Psalm/Report/ByIssueLevelAndTypeReport.php b/src/Psalm/Report/ByIssueLevelAndTypeReport.php index e3e4e54db5f..a4c6975d40e 100644 --- a/src/Psalm/Report/ByIssueLevelAndTypeReport.php +++ b/src/Psalm/Report/ByIssueLevelAndTypeReport.php @@ -166,8 +166,7 @@ private function getFileReference(IssueData|DataFlowNodeData $data): string if (null === $this->link_format) { // if xdebug is not enabled, use `get_cfg_var` to get the value directly from php.ini - $this->link_format = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') - ?: 'file://%f#L%l'; + $this->link_format = (ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: 'file://%f#L%l'; } $link = strtr($this->link_format, ['%f' => $data->file_path, '%l' => $data->line_from]); diff --git a/src/Psalm/Report/CodeClimateReport.php b/src/Psalm/Report/CodeClimateReport.php index fb0cbf28689..9fd215026f0 100644 --- a/src/Psalm/Report/CodeClimateReport.php +++ b/src/Psalm/Report/CodeClimateReport.php @@ -28,7 +28,7 @@ public function create(): string $options = $this->pretty ? Json::PRETTY : Json::DEFAULT; $issues_data = array_map( - [$this, 'mapToNewStructure'], + $this->mapToNewStructure(...), $this->issues_data, ); diff --git a/src/Psalm/Report/ConsoleReport.php b/src/Psalm/Report/ConsoleReport.php index ee34a67b864..f8a4b4e2441 100644 --- a/src/Psalm/Report/ConsoleReport.php +++ b/src/Psalm/Report/ConsoleReport.php @@ -134,8 +134,7 @@ private function getFileReference(IssueData|DataFlowNodeData $data): string if (null === $this->link_format) { // if xdebug is not enabled, use `get_cfg_var` to get the value directly from php.ini - $this->link_format = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') - ?: 'file://%f#L%l'; + $this->link_format = (ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: 'file://%f#L%l'; } $link = strtr($this->link_format, ['%f' => $data->file_path, '%l' => $data->line_from]); diff --git a/src/Psalm/Report/SarifReport.php b/src/Psalm/Report/SarifReport.php index c16680ca5f3..463468ce60b 100644 --- a/src/Psalm/Report/SarifReport.php +++ b/src/Psalm/Report/SarifReport.php @@ -11,7 +11,7 @@ use function file_exists; use function file_get_contents; -use function strpos; +use function str_starts_with; /** * SARIF report format suitable for import into any SARIF compatible solution @@ -50,7 +50,7 @@ public function create(): string ], 'properties' => [ 'tags' => [ - (strpos($issue_data->type, 'Tainted') === 0) ? 'security' : 'maintainability', + (str_starts_with($issue_data->type, 'Tainted')) ? 'security' : 'maintainability', ], ], 'helpUri' => $issue_data->link, diff --git a/src/Psalm/SourceControl/Git/GitInfo.php b/src/Psalm/SourceControl/Git/GitInfo.php index dd7927255fa..c937e748cc6 100644 --- a/src/Psalm/SourceControl/Git/GitInfo.php +++ b/src/Psalm/SourceControl/Git/GitInfo.php @@ -31,23 +31,6 @@ */ final class GitInfo extends SourceControlInfo { - /** - * Branch name. - */ - protected string $branch; - - /** - * Head. - */ - protected CommitInfo $head; - - /** - * Remote. - * - * @var RemoteInfo[] - */ - protected array $remotes; - /** * Constructor. * @@ -55,11 +38,14 @@ final class GitInfo extends SourceControlInfo * @param CommitInfo $head HEAD commit * @param RemoteInfo[] $remotes remote repositories */ - public function __construct(string $branch, CommitInfo $head, array $remotes) - { - $this->branch = $branch; - $this->head = $head; - $this->remotes = $remotes; + public function __construct( + protected string $branch, + protected CommitInfo $head, + /** + * Remote. + */ + protected array $remotes, + ) { } public function toArray(): array diff --git a/src/Psalm/Storage/Assertion.php b/src/Psalm/Storage/Assertion.php index 522af5078f6..3ab86c58f09 100644 --- a/src/Psalm/Storage/Assertion.php +++ b/src/Psalm/Storage/Assertion.php @@ -5,11 +5,12 @@ namespace Psalm\Storage; use Psalm\Type\Atomic; +use Stringable; /** * @psalm-immutable */ -abstract class Assertion +abstract class Assertion implements Stringable { use ImmutableNonCloneableTrait; diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php b/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php index 83076312120..f7f23955ffe 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php @@ -11,13 +11,9 @@ */ final class DoesNotHaveAtLeastCount extends Assertion { - /** @var positive-int */ - public int $count; - /** @param positive-int $count */ - public function __construct(int $count) + public function __construct(public int $count) { - $this->count = $count; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php b/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php index cc96639ddf0..39727d14979 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php @@ -11,13 +11,9 @@ */ final class DoesNotHaveExactCount extends Assertion { - /** @var positive-int */ - public int $count; - /** @param positive-int $count */ - public function __construct(int $count) + public function __construct(public int $count) { - $this->count = $count; } public function isNegation(): bool diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php b/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php index fbd25e22ae6..a760247603a 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php @@ -11,11 +11,8 @@ */ final class DoesNotHaveMethod extends Assertion { - public string $method; - - public function __construct(string $method) + public function __construct(public string $method) { - $this->method = $method; } public function isNegation(): bool diff --git a/src/Psalm/Storage/Assertion/HasAtLeastCount.php b/src/Psalm/Storage/Assertion/HasAtLeastCount.php index 0c2555b9994..c15a40435be 100644 --- a/src/Psalm/Storage/Assertion/HasAtLeastCount.php +++ b/src/Psalm/Storage/Assertion/HasAtLeastCount.php @@ -11,13 +11,9 @@ */ final class HasAtLeastCount extends Assertion { - /** @var positive-int */ - public int $count; - /** @param positive-int $count */ - public function __construct(int $count) + public function __construct(public int $count) { - $this->count = $count; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/HasExactCount.php b/src/Psalm/Storage/Assertion/HasExactCount.php index 8f468b1eda4..41f03b627e1 100644 --- a/src/Psalm/Storage/Assertion/HasExactCount.php +++ b/src/Psalm/Storage/Assertion/HasExactCount.php @@ -11,13 +11,9 @@ */ final class HasExactCount extends Assertion { - /** @var positive-int */ - public int $count; - /** @param positive-int $count */ - public function __construct(int $count) + public function __construct(public int $count) { - $this->count = $count; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/HasMethod.php b/src/Psalm/Storage/Assertion/HasMethod.php index c4cb22a506b..1d18a3a1933 100644 --- a/src/Psalm/Storage/Assertion/HasMethod.php +++ b/src/Psalm/Storage/Assertion/HasMethod.php @@ -11,11 +11,8 @@ */ final class HasMethod extends Assertion { - public string $method; - - public function __construct(string $method) + public function __construct(public string $method) { - $this->method = $method; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/InArray.php b/src/Psalm/Storage/Assertion/InArray.php index 2e63d15457a..0ef928f5bd9 100644 --- a/src/Psalm/Storage/Assertion/InArray.php +++ b/src/Psalm/Storage/Assertion/InArray.php @@ -12,11 +12,8 @@ */ final class InArray extends Assertion { - public Union $type; - - public function __construct(Union $type) + public function __construct(public Union $type) { - $this->type = $type; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/IsAClass.php b/src/Psalm/Storage/Assertion/IsAClass.php index c7476bc9532..daf178c5f24 100644 --- a/src/Psalm/Storage/Assertion/IsAClass.php +++ b/src/Psalm/Storage/Assertion/IsAClass.php @@ -12,15 +12,9 @@ */ final class IsAClass extends Assertion { - /** @var Atomic\TTemplateParamClass|Atomic\TNamedObject */ - public Atomic $type; - public bool $allow_string; - /** @param Atomic\TTemplateParamClass|Atomic\TNamedObject $type */ - public function __construct(Atomic $type, bool $allow_string) + public function __construct(public Atomic $type, public bool $allow_string) { - $this->type = $type; - $this->allow_string = $allow_string; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/IsClassEqual.php b/src/Psalm/Storage/Assertion/IsClassEqual.php index 4f51e7b323f..e0dce8d388c 100644 --- a/src/Psalm/Storage/Assertion/IsClassEqual.php +++ b/src/Psalm/Storage/Assertion/IsClassEqual.php @@ -11,11 +11,8 @@ */ final class IsClassEqual extends Assertion { - public string $type; - - public function __construct(string $type) + public function __construct(public string $type) { - $this->type = $type; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/IsClassNotEqual.php b/src/Psalm/Storage/Assertion/IsClassNotEqual.php index 8fd8508654e..67044932a47 100644 --- a/src/Psalm/Storage/Assertion/IsClassNotEqual.php +++ b/src/Psalm/Storage/Assertion/IsClassNotEqual.php @@ -11,11 +11,8 @@ */ final class IsClassNotEqual extends Assertion { - public string $type; - - public function __construct(string $type) + public function __construct(public string $type) { - $this->type = $type; } public function isNegation(): bool diff --git a/src/Psalm/Storage/Assertion/IsGreaterThan.php b/src/Psalm/Storage/Assertion/IsGreaterThan.php index 175f571a1cc..28d7122767d 100644 --- a/src/Psalm/Storage/Assertion/IsGreaterThan.php +++ b/src/Psalm/Storage/Assertion/IsGreaterThan.php @@ -11,11 +11,8 @@ */ final class IsGreaterThan extends Assertion { - public int $value; - - public function __construct(int $value) + public function __construct(public int $value) { - $this->value = $value; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php b/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php index ffdb3bbf44f..6e3f16d39ad 100644 --- a/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php +++ b/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php @@ -11,11 +11,8 @@ */ final class IsGreaterThanOrEqualTo extends Assertion { - public int $value; - - public function __construct(int $value) + public function __construct(public int $value) { - $this->value = $value; } public function isNegation(): bool diff --git a/src/Psalm/Storage/Assertion/IsIdentical.php b/src/Psalm/Storage/Assertion/IsIdentical.php index b703c59fce2..90193fc9ca2 100644 --- a/src/Psalm/Storage/Assertion/IsIdentical.php +++ b/src/Psalm/Storage/Assertion/IsIdentical.php @@ -12,11 +12,8 @@ */ final class IsIdentical extends Assertion { - public Atomic $type; - - public function __construct(Atomic $type) + public function __construct(public Atomic $type) { - $this->type = $type; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/IsLessThan.php b/src/Psalm/Storage/Assertion/IsLessThan.php index 3708dd08695..d4236b65058 100644 --- a/src/Psalm/Storage/Assertion/IsLessThan.php +++ b/src/Psalm/Storage/Assertion/IsLessThan.php @@ -11,11 +11,8 @@ */ final class IsLessThan extends Assertion { - public int $value; - - public function __construct(int $value) + public function __construct(public int $value) { - $this->value = $value; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php b/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php index 13aef9d02e8..5250d2da78d 100644 --- a/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php +++ b/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php @@ -11,11 +11,8 @@ */ final class IsLessThanOrEqualTo extends Assertion { - public int $value; - - public function __construct(int $value) + public function __construct(public int $value) { - $this->value = $value; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/IsLooselyEqual.php b/src/Psalm/Storage/Assertion/IsLooselyEqual.php index 7c145edeb9c..5fdd85d4ec9 100644 --- a/src/Psalm/Storage/Assertion/IsLooselyEqual.php +++ b/src/Psalm/Storage/Assertion/IsLooselyEqual.php @@ -12,11 +12,8 @@ */ final class IsLooselyEqual extends Assertion { - public Atomic $type; - - public function __construct(Atomic $type) + public function __construct(public Atomic $type) { - $this->type = $type; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/IsNotAClass.php b/src/Psalm/Storage/Assertion/IsNotAClass.php index b474b3ad85e..a94327a88b3 100644 --- a/src/Psalm/Storage/Assertion/IsNotAClass.php +++ b/src/Psalm/Storage/Assertion/IsNotAClass.php @@ -12,15 +12,9 @@ */ final class IsNotAClass extends Assertion { - /** @var Atomic\TTemplateParamClass|Atomic\TNamedObject */ - public Atomic $type; - public bool $allow_string; - /** @param Atomic\TTemplateParamClass|Atomic\TNamedObject $type */ - public function __construct(Atomic $type, bool $allow_string) + public function __construct(public Atomic $type, public bool $allow_string) { - $this->type = $type; - $this->allow_string = $allow_string; } public function isNegation(): bool diff --git a/src/Psalm/Storage/Assertion/IsNotIdentical.php b/src/Psalm/Storage/Assertion/IsNotIdentical.php index f483cef0293..6dcfa2b908d 100644 --- a/src/Psalm/Storage/Assertion/IsNotIdentical.php +++ b/src/Psalm/Storage/Assertion/IsNotIdentical.php @@ -12,11 +12,8 @@ */ final class IsNotIdentical extends Assertion { - public Atomic $type; - - public function __construct(Atomic $type) + public function __construct(public Atomic $type) { - $this->type = $type; } public function isNegation(): bool diff --git a/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php b/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php index 3715553273e..0a1f9f1abd3 100644 --- a/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php +++ b/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php @@ -12,11 +12,8 @@ */ final class IsNotLooselyEqual extends Assertion { - public Atomic $type; - - public function __construct(Atomic $type) + public function __construct(public Atomic $type) { - $this->type = $type; } public function isNegation(): bool diff --git a/src/Psalm/Storage/Assertion/IsNotType.php b/src/Psalm/Storage/Assertion/IsNotType.php index 090a8e4abf0..ff07df64287 100644 --- a/src/Psalm/Storage/Assertion/IsNotType.php +++ b/src/Psalm/Storage/Assertion/IsNotType.php @@ -12,11 +12,8 @@ */ final class IsNotType extends Assertion { - public Atomic $type; - - public function __construct(Atomic $type) + public function __construct(public Atomic $type) { - $this->type = $type; } public function isNegation(): bool diff --git a/src/Psalm/Storage/Assertion/IsType.php b/src/Psalm/Storage/Assertion/IsType.php index 37fc63d66ed..f1e5f1e3d51 100644 --- a/src/Psalm/Storage/Assertion/IsType.php +++ b/src/Psalm/Storage/Assertion/IsType.php @@ -12,11 +12,8 @@ */ final class IsType extends Assertion { - public Atomic $type; - - public function __construct(Atomic $type) + public function __construct(public Atomic $type) { - $this->type = $type; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/NestedAssertions.php b/src/Psalm/Storage/Assertion/NestedAssertions.php index 59010690a8d..b8281f9d22f 100644 --- a/src/Psalm/Storage/Assertion/NestedAssertions.php +++ b/src/Psalm/Storage/Assertion/NestedAssertions.php @@ -15,13 +15,9 @@ */ final class NestedAssertions extends Assertion { - /** @var array>> */ - public array $assertions; - /** @param array>> $assertions */ - public function __construct(array $assertions) + public function __construct(public array $assertions) { - $this->assertions = $assertions; } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/NotInArray.php b/src/Psalm/Storage/Assertion/NotInArray.php index 824ed5db303..af24e98de59 100644 --- a/src/Psalm/Storage/Assertion/NotInArray.php +++ b/src/Psalm/Storage/Assertion/NotInArray.php @@ -12,14 +12,12 @@ */ final class NotInArray extends Assertion { - /** - * @readonly - */ - public Union $type; - - public function __construct(Union $type) - { - $this->type = $type; + public function __construct( + /** + * @readonly + */ + public Union $type, + ) { } public function getNegation(): Assertion diff --git a/src/Psalm/Storage/Assertion/NotNestedAssertions.php b/src/Psalm/Storage/Assertion/NotNestedAssertions.php index f3d932ae498..b69ec8f5f69 100644 --- a/src/Psalm/Storage/Assertion/NotNestedAssertions.php +++ b/src/Psalm/Storage/Assertion/NotNestedAssertions.php @@ -15,13 +15,9 @@ */ final class NotNestedAssertions extends Assertion { - /** @var array>> */ - public array $assertions; - /** @param array>> $assertions */ - public function __construct(array $assertions) + public function __construct(public array $assertions) { - $this->assertions = $assertions; } public function isNegation(): bool diff --git a/src/Psalm/Storage/AttributeArg.php b/src/Psalm/Storage/AttributeArg.php index 72fd6080222..b8fe640932b 100644 --- a/src/Psalm/Storage/AttributeArg.php +++ b/src/Psalm/Storage/AttributeArg.php @@ -14,25 +14,17 @@ final class AttributeArg { use ImmutableNonCloneableTrait; - /** - * @psalm-suppress PossiblyUnusedProperty It's part of the public API for now - */ - public ?string $name = null; - - public Union|UnresolvedConstantComponent $type; - - /** - * @psalm-suppress PossiblyUnusedProperty It's part of the public API for now - */ - public CodeLocation $location; public function __construct( - ?string $name, - Union|UnresolvedConstantComponent $type, - CodeLocation $location, + /** + * @psalm-suppress PossiblyUnusedProperty It's part of the public API for now + */ + public ?string $name, + public Union|UnresolvedConstantComponent $type, + /** + * @psalm-suppress PossiblyUnusedProperty It's part of the public API for now + */ + public CodeLocation $location, ) { - $this->name = $name; - $this->type = $type; - $this->location = $location; } } diff --git a/src/Psalm/Storage/AttributeStorage.php b/src/Psalm/Storage/AttributeStorage.php index 8cbc499a637..0e6ad44a31d 100644 --- a/src/Psalm/Storage/AttributeStorage.php +++ b/src/Psalm/Storage/AttributeStorage.php @@ -12,35 +12,21 @@ final class AttributeStorage { use ImmutableNonCloneableTrait; - public string $fq_class_name; - - /** - * @var list - */ - public array $args; - - /** - * @psalm-suppress PossiblyUnusedProperty part of public API - */ - public CodeLocation $location; - - /** - * @psalm-suppress PossiblyUnusedProperty part of public API - */ - public CodeLocation $name_location; /** * @param list $args */ public function __construct( - string $fq_class_name, - array $args, - CodeLocation $location, - CodeLocation $name_location, + public string $fq_class_name, + public array $args, + /** + * @psalm-suppress PossiblyUnusedProperty part of public API + */ + public CodeLocation $location, + /** + * @psalm-suppress PossiblyUnusedProperty part of public API + */ + public CodeLocation $name_location, ) { - $this->fq_class_name = $fq_class_name; - $this->args = $args; - $this->location = $location; - $this->name_location = $name_location; } } diff --git a/src/Psalm/Storage/ClassConstantStorage.php b/src/Psalm/Storage/ClassConstantStorage.php index 78488412a81..e7fe4e36700 100644 --- a/src/Psalm/Storage/ClassConstantStorage.php +++ b/src/Psalm/Storage/ClassConstantStorage.php @@ -22,76 +22,31 @@ final class ClassConstantStorage use CustomMetadataTrait; use ImmutableNonCloneableTrait; - public ?CodeLocation $type_location; - - /** - * The type from an annotation, or the inferred type if no annotation exists. - */ - public ?Union $type; - - /** - * The type inferred from the value. - */ - public ?Union $inferred_type; - - /** - * @var ClassLikeAnalyzer::VISIBILITY_* - */ - public int $visibility = ClassLikeAnalyzer::VISIBILITY_PUBLIC; - - public ?CodeLocation $location; - - public ?CodeLocation $stmt_location; - - public ?UnresolvedConstantComponent $unresolved_node; - - public bool $deprecated = false; - - public bool $final = false; - - /** - * @var list - */ - public array $attributes = []; - - /** - * @var array - */ - public array $suppressed_issues = []; - - public ?string $description; - /** * @param ClassLikeAnalyzer::VISIBILITY_* $visibility * @param list $attributes * @param array $suppressed_issues */ public function __construct( - ?Union $type, - ?Union $inferred_type, - int $visibility, - ?CodeLocation $location, - ?CodeLocation $type_location = null, - ?CodeLocation $stmt_location = null, - bool $deprecated = false, - bool $final = false, - ?UnresolvedConstantComponent $unresolved_node = null, - array $attributes = [], - array $suppressed_issues = [], - ?string $description = null, + /** + * The type from an annotation, or the inferred type if no annotation exists. + */ + public ?Union $type, + /** + * The type inferred from the value. + */ + public ?Union $inferred_type, + public int $visibility, + public ?CodeLocation $location, + public ?CodeLocation $type_location = null, + public ?CodeLocation $stmt_location = null, + public bool $deprecated = false, + public bool $final = false, + public ?UnresolvedConstantComponent $unresolved_node = null, + public array $attributes = [], + public array $suppressed_issues = [], + public ?string $description = null, ) { - $this->visibility = $visibility; - $this->location = $location; - $this->type = $type; - $this->inferred_type = $inferred_type; - $this->type_location = $type_location; - $this->stmt_location = $stmt_location; - $this->deprecated = $deprecated; - $this->final = $final; - $this->unresolved_node = $unresolved_node; - $this->attributes = $attributes; - $this->suppressed_issues = $suppressed_issues; - $this->description = $description; } /** @@ -99,18 +54,11 @@ public function __construct( */ public function getHoverMarkdown(string $const): string { - switch ($this->visibility) { - case ClassLikeAnalyzer::VISIBILITY_PRIVATE: - $visibility_text = 'private'; - break; - - case ClassLikeAnalyzer::VISIBILITY_PROTECTED: - $visibility_text = 'protected'; - break; - - default: - $visibility_text = 'public'; - } + $visibility_text = match ($this->visibility) { + ClassLikeAnalyzer::VISIBILITY_PRIVATE => 'private', + ClassLikeAnalyzer::VISIBILITY_PROTECTED => 'protected', + default => 'public', + }; $value = ''; if ($this->type) { diff --git a/src/Psalm/Storage/ClassLikeStorage.php b/src/Psalm/Storage/ClassLikeStorage.php index 8fabc2e3edd..e6849ebf2f7 100644 --- a/src/Psalm/Storage/ClassLikeStorage.php +++ b/src/Psalm/Storage/ClassLikeStorage.php @@ -68,8 +68,6 @@ final class ClassLikeStorage implements HasAttributesInterface */ public array $suppressed_issues = []; - public string $name; - /** * Is this class user-defined */ @@ -388,9 +386,8 @@ final class ClassLikeStorage implements HasAttributesInterface public bool $readonly = false; - public function __construct(string $name) + public function __construct(public string $name) { - $this->name = $name; } /** diff --git a/src/Psalm/Storage/EnumCaseStorage.php b/src/Psalm/Storage/EnumCaseStorage.php index 12cf8b1098e..08b428ad1de 100644 --- a/src/Psalm/Storage/EnumCaseStorage.php +++ b/src/Psalm/Storage/EnumCaseStorage.php @@ -10,17 +10,9 @@ final class EnumCaseStorage { - public TLiteralString|TLiteralInt|null $value = null; - - public CodeLocation $stmt_location; - public bool $deprecated = false; - public function __construct( - TLiteralString|TLiteralInt|null $value, - CodeLocation $location, - ) { - $this->value = $value; - $this->stmt_location = $location; + public function __construct(public TLiteralString|TLiteralInt|null $value, public CodeLocation $stmt_location) + { } } diff --git a/src/Psalm/Storage/FileStorage.php b/src/Psalm/Storage/FileStorage.php index ce309152bba..1fa76277098 100644 --- a/src/Psalm/Storage/FileStorage.php +++ b/src/Psalm/Storage/FileStorage.php @@ -33,8 +33,6 @@ final class FileStorage */ public array $required_interfaces = []; - public string $file_path; - /** * @var array */ @@ -87,8 +85,7 @@ final class FileStorage /** @var Aliases[] */ public array $namespace_aliases = []; - public function __construct(string $file_path) + public function __construct(public string $file_path) { - $this->file_path = $file_path; } } diff --git a/src/Psalm/Storage/FunctionLikeParameter.php b/src/Psalm/Storage/FunctionLikeParameter.php index cdeaee2d3eb..ec35edd8763 100644 --- a/src/Psalm/Storage/FunctionLikeParameter.php +++ b/src/Psalm/Storage/FunctionLikeParameter.php @@ -15,32 +15,10 @@ final class FunctionLikeParameter implements HasAttributesInterface, TypeNode { use CustomMetadataTrait; - public string $name; - - public bool $by_ref; - - public ?Union $type = null; - - public ?Union $out_type = null; - - public ?Union $signature_type = null; - public bool $has_docblock_type = false; - public bool $is_optional; - - public bool $is_nullable; - - public Union|UnresolvedConstantComponent|null $default_type = null; - - public ?CodeLocation $location = null; - - public ?CodeLocation $type_location = null; - public ?CodeLocation $signature_type_location = null; - public bool $is_variadic; - /** * @var array|null */ @@ -65,30 +43,19 @@ final class FunctionLikeParameter implements HasAttributesInterface, TypeNode * @psalm-external-mutation-free */ public function __construct( - string $name, - bool $by_ref, - ?Union $type = null, - ?Union $signature_type = null, - ?CodeLocation $location = null, - ?CodeLocation $type_location = null, - bool $is_optional = true, - bool $is_nullable = false, - bool $is_variadic = false, - Union|UnresolvedConstantComponent|null $default_type = null, - ?Union $out_type = null, + public string $name, + public bool $by_ref, + public ?Union $type = null, + public ?Union $signature_type = null, + public ?CodeLocation $location = null, + public ?CodeLocation $type_location = null, + public bool $is_optional = true, + public bool $is_nullable = false, + public bool $is_variadic = false, + public Union|UnresolvedConstantComponent|null $default_type = null, + public ?Union $out_type = null, ) { - $this->name = $name; - $this->by_ref = $by_ref; - $this->type = $type; - $this->signature_type = $signature_type; - $this->is_optional = $is_optional; - $this->is_nullable = $is_nullable; - $this->is_variadic = $is_variadic; - $this->location = $location; - $this->type_location = $type_location; $this->signature_type_location = $type_location; - $this->default_type = $default_type; - $this->out_type = $out_type; } /** @psalm-mutation-free */ diff --git a/src/Psalm/Storage/FunctionLikeStorage.php b/src/Psalm/Storage/FunctionLikeStorage.php index ef13057d9dc..5fd48feb486 100644 --- a/src/Psalm/Storage/FunctionLikeStorage.php +++ b/src/Psalm/Storage/FunctionLikeStorage.php @@ -8,6 +8,7 @@ use Psalm\Internal\Analyzer\ClassLikeAnalyzer; use Psalm\Issue\CodeIssue; use Psalm\Type\Union; +use Stringable; use function array_column; use function array_fill_keys; @@ -15,7 +16,7 @@ use function count; use function implode; -abstract class FunctionLikeStorage implements HasAttributesInterface +abstract class FunctionLikeStorage implements HasAttributesInterface, Stringable { use CustomMetadataTrait; @@ -209,18 +210,11 @@ function (FunctionLikeParameter $param): string { return $symbol_text; } - switch ($this->visibility) { - case ClassLikeAnalyzer::VISIBILITY_PRIVATE: - $visibility_text = 'private'; - break; - - case ClassLikeAnalyzer::VISIBILITY_PROTECTED: - $visibility_text = 'protected'; - break; - - default: - $visibility_text = 'public'; - } + $visibility_text = match ($this->visibility) { + ClassLikeAnalyzer::VISIBILITY_PRIVATE => 'private', + ClassLikeAnalyzer::VISIBILITY_PROTECTED => 'protected', + default => 'public', + }; return $visibility_text . ' ' . $symbol_text; } @@ -239,18 +233,11 @@ public function getCompletionSignature(): string return $symbol_text; } - switch ($this->visibility) { - case ClassLikeAnalyzer::VISIBILITY_PRIVATE: - $visibility_text = 'private'; - break; - - case ClassLikeAnalyzer::VISIBILITY_PROTECTED: - $visibility_text = 'protected'; - break; - - default: - $visibility_text = 'public'; - } + $visibility_text = match ($this->visibility) { + ClassLikeAnalyzer::VISIBILITY_PRIVATE => 'private', + ClassLikeAnalyzer::VISIBILITY_PROTECTED => 'protected', + default => 'public', + }; return $visibility_text . ' ' . $symbol_text; } diff --git a/src/Psalm/Storage/Possibilities.php b/src/Psalm/Storage/Possibilities.php index 62959661725..88c2df08e70 100644 --- a/src/Psalm/Storage/Possibilities.php +++ b/src/Psalm/Storage/Possibilities.php @@ -14,24 +14,17 @@ final class Possibilities { - /** - * @var list the rule being asserted - */ - public array $rule; - - /** - * @var int|string the id of the property/variable, or - * the parameter offset of the affected arg - */ - public int|string $var_id; - /** * @param list $rule */ - public function __construct(string|int $var_id, array $rule) - { - $this->rule = $rule; - $this->var_id = $var_id; + public function __construct( + /** + * @var int|string the id of the property/variable, or + * the parameter offset of the affected arg + */ + public int|string $var_id, + public array $rule, + ) { } public function getUntemplatedCopy( diff --git a/src/Psalm/Storage/PropertyStorage.php b/src/Psalm/Storage/PropertyStorage.php index 3eb742c281e..20bf24f5bc3 100644 --- a/src/Psalm/Storage/PropertyStorage.php +++ b/src/Psalm/Storage/PropertyStorage.php @@ -67,18 +67,11 @@ final class PropertyStorage implements HasAttributesInterface public function getInfo(): string { - switch ($this->visibility) { - case ClassLikeAnalyzer::VISIBILITY_PRIVATE: - $visibility_text = 'private'; - break; - - case ClassLikeAnalyzer::VISIBILITY_PROTECTED: - $visibility_text = 'protected'; - break; - - default: - $visibility_text = 'public'; - } + $visibility_text = match ($this->visibility) { + ClassLikeAnalyzer::VISIBILITY_PRIVATE => 'private', + ClassLikeAnalyzer::VISIBILITY_PROTECTED => 'protected', + default => 'public', + }; return $visibility_text . ' ' . ($this->type ? $this->type->getId() : 'mixed'); } diff --git a/src/Psalm/Type.php b/src/Psalm/Type.php index 7960ef264b6..445a2e23500 100644 --- a/src/Psalm/Type.php +++ b/src/Psalm/Type.php @@ -58,11 +58,11 @@ use function array_shift; use function array_values; use function explode; -use function get_class; use function implode; use function is_int; use function preg_quote; use function preg_replace; +use function str_contains; use function stripos; use function strlen; use function strpos; @@ -104,7 +104,7 @@ public static function getFQCLNFromString( $imported_namespaces = $aliases->uses; - if (strpos($class, '\\') !== false) { + if (str_contains($class, '\\')) { $class_parts = explode('\\', $class); $first_namespace = array_shift($class_parts); @@ -155,7 +155,7 @@ public static function getStringFromFQCLN( if (!isset($aliased_classes[strtolower($candidate_parts[0])])) { return $candidate; } - } elseif (!$namespace && strpos($value, '\\') === false) { + } elseif (!$namespace && !str_contains($value, '\\')) { return $value; } @@ -628,13 +628,13 @@ public static function combineUnionTypes( $both_failed_reconciliation = true; } else { return $type_2->setProperties([ - 'parent_nodes' => array_merge($type_2->parent_nodes, $type_1->parent_nodes), + 'parent_nodes' => [...$type_2->parent_nodes, ...$type_1->parent_nodes], 'possibly_undefined' => $possibly_undefined ?? $type_2->possibly_undefined, ]); } } elseif ($type_2->failed_reconciliation) { return $type_1->setProperties([ - 'parent_nodes' => array_merge($type_1->parent_nodes, $type_2->parent_nodes), + 'parent_nodes' => [...$type_1->parent_nodes, ...$type_2->parent_nodes], 'possibly_undefined' => $possibly_undefined ?? $type_1->possibly_undefined, ]); } @@ -848,15 +848,15 @@ private static function intersectAtomicTypes( && $type_2_atomic instanceof TNamedObject ) { if (($type_1_atomic->value === $type_2_atomic->value - && get_class($type_1_atomic) === TNamedObject::class - && get_class($type_2_atomic) !== TNamedObject::class) + && $type_1_atomic::class === TNamedObject::class + && $type_2_atomic::class !== TNamedObject::class) ) { $intersection_atomic = $type_2_atomic; $wider_type = $type_1_atomic; $intersection_performed = true; } elseif (($type_1_atomic->value === $type_2_atomic->value - && get_class($type_2_atomic) === TNamedObject::class - && get_class($type_1_atomic) !== TNamedObject::class) + && $type_2_atomic::class === TNamedObject::class + && $type_1_atomic::class !== TNamedObject::class) ) { $intersection_atomic = $type_1_atomic; $wider_type = $type_2_atomic; @@ -921,7 +921,7 @@ private static function intersectAtomicTypes( if ($first_is_class && $second_is_class) { return $intersection_atomic; } - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // Ignore non-existing classes during initial scan } } @@ -983,7 +983,7 @@ private static function mayHaveIntersection(Atomic $type, Codebase $codebase): b } try { $storage = $codebase->classlike_storage_provider->get($type->value); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { // Ignore non-existing classes during initial scan return true; } diff --git a/src/Psalm/Type/Atomic.php b/src/Psalm/Type/Atomic.php index b80d0af22a0..0c54b964716 100644 --- a/src/Psalm/Type/Atomic.php +++ b/src/Psalm/Type/Atomic.php @@ -66,24 +66,28 @@ use Psalm\Type\Atomic\TTrue; use Psalm\Type\Atomic\TTypeAlias; use Psalm\Type\Atomic\TVoid; +use Stringable; use function array_filter; use function array_keys; use function count; -use function get_class; use function is_array; use function is_numeric; +use function str_starts_with; use function strpos; use function strtolower; /** * @psalm-immutable */ -abstract class Atomic implements TypeNode +abstract class Atomic implements TypeNode, Stringable { - public function __construct(bool $from_docblock = false) - { - $this->from_docblock = $from_docblock; + public function __construct( + /** + * Whether or not the type comes from a docblock + */ + public bool $from_docblock = false, + ) { } protected function __clone() { @@ -94,11 +98,6 @@ protected function __clone() */ public bool $checked = false; - /** - * Whether or not the type comes from a docblock - */ - public bool $from_docblock = false; - public ?int $offset_start = null; public ?int $offset_end = null; @@ -385,7 +384,7 @@ private static function createInner( return new TClosure('Closure'); } - if (strpos($value, '-') && strpos($value, 'OCI-') !== 0) { + if (strpos($value, '-') && !str_starts_with($value, 'OCI-')) { throw new TypeParseTreeException('Unrecognized type ' . $value); } @@ -767,7 +766,7 @@ public function replaceTemplateTypesWithArgTypes( public function equals(Atomic $other_type, bool $ensure_source_equality): bool { - return get_class($other_type) === get_class($this); + return $other_type::class === static::class; } public function isTruthy(): bool diff --git a/src/Psalm/Type/Atomic/GenericTrait.php b/src/Psalm/Type/Atomic/GenericTrait.php index e35a72fdfee..a9c9dc7cac7 100644 --- a/src/Psalm/Type/Atomic/GenericTrait.php +++ b/src/Psalm/Type/Atomic/GenericTrait.php @@ -105,9 +105,9 @@ public function toNamespacedString( return $value_type_string . '[]'; } - $intersection_pos = strpos($base_value, '&'); + $intersection_pos = strpos((string) $base_value, '&'); if ($intersection_pos !== false) { - $base_value = substr($base_value, 0, $intersection_pos); + $base_value = substr((string) $base_value, 0, $intersection_pos); } $type_params = $this->type_params; diff --git a/src/Psalm/Type/Atomic/TAnonymousClassInstance.php b/src/Psalm/Type/Atomic/TAnonymousClassInstance.php index d92a2f2f0b6..7481dee2554 100644 --- a/src/Psalm/Type/Atomic/TAnonymousClassInstance.php +++ b/src/Psalm/Type/Atomic/TAnonymousClassInstance.php @@ -11,8 +11,6 @@ */ final class TAnonymousClassInstance extends TNamedObject { - public ?string $extends = null; - /** * @param string $value the name of the object * @param array $extra_types @@ -20,12 +18,10 @@ final class TAnonymousClassInstance extends TNamedObject public function __construct( string $value, bool $is_static = false, - ?string $extends = null, + public ?string $extends = null, array $extra_types = [], ) { parent::__construct($value, $is_static, false, $extra_types); - - $this->extends = $extends; } public function toPhpString( diff --git a/src/Psalm/Type/Atomic/TArray.php b/src/Psalm/Type/Atomic/TArray.php index cf90faf8851..0625388e961 100644 --- a/src/Psalm/Type/Atomic/TArray.php +++ b/src/Psalm/Type/Atomic/TArray.php @@ -11,7 +11,6 @@ use Psalm\Type\Union; use function count; -use function get_class; /** * Denotes a simple array of the form `array`. It expects an array with two elements, both union types. @@ -67,7 +66,7 @@ public function canBeFullyExpressedInPhp(int $analysis_php_version_id): bool public function equals(Atomic $other_type, bool $ensure_source_equality): bool { - if (get_class($other_type) !== static::class) { + if ($other_type::class !== static::class) { return false; } diff --git a/src/Psalm/Type/Atomic/TCallableObject.php b/src/Psalm/Type/Atomic/TCallableObject.php index 053dbfb3b0a..58452bd5ce9 100644 --- a/src/Psalm/Type/Atomic/TCallableObject.php +++ b/src/Psalm/Type/Atomic/TCallableObject.php @@ -13,12 +13,9 @@ final class TCallableObject extends TObject { use HasIntersectionTrait; - public ?TCallable $callable; - - public function __construct(bool $from_docblock = false, ?TCallable $callable = null) + public function __construct(bool $from_docblock = false, public ?TCallable $callable = null) { parent::__construct($from_docblock); - $this->callable = $callable; } public function getKey(bool $include_extra = true): string diff --git a/src/Psalm/Type/Atomic/TClassConstant.php b/src/Psalm/Type/Atomic/TClassConstant.php index 217877448b7..7dfbba4a323 100644 --- a/src/Psalm/Type/Atomic/TClassConstant.php +++ b/src/Psalm/Type/Atomic/TClassConstant.php @@ -14,14 +14,8 @@ */ final class TClassConstant extends Atomic { - public string $fq_classlike_name; - - public string $const_name; - - public function __construct(string $fq_classlike_name, string $const_name, bool $from_docblock = false) + public function __construct(public string $fq_classlike_name, public string $const_name, bool $from_docblock = false) { - $this->fq_classlike_name = $fq_classlike_name; - $this->const_name = $const_name; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TClassString.php b/src/Psalm/Type/Atomic/TClassString.php index f994601666a..5a384a3755a 100644 --- a/src/Psalm/Type/Atomic/TClassString.php +++ b/src/Psalm/Type/Atomic/TClassString.php @@ -15,8 +15,8 @@ use function count; use function preg_quote; use function preg_replace; +use function str_contains; use function stripos; -use function strpos; use function strtolower; /** @@ -27,29 +27,14 @@ */ class TClassString extends TString { - public string $as; - - public ?TNamedObject $as_type; - - public bool $is_loaded = false; - - public bool $is_interface = false; - - public bool $is_enum = false; - public function __construct( - string $as = 'object', - ?TNamedObject $as_type = null, - bool $is_loaded = false, - bool $is_interface = false, - bool $is_enum = false, + public string $as = 'object', + public ?TNamedObject $as_type = null, + public bool $is_loaded = false, + public bool $is_interface = false, + public bool $is_enum = false, bool $from_docblock = false, ) { - $this->as = $as; - $this->as_type = $as_type; - $this->is_loaded = $is_loaded; - $this->is_interface = $is_interface; - $this->is_enum = $is_enum; parent::__construct($from_docblock); } /** @@ -129,7 +114,7 @@ public function toNamespacedString( ) . '>'; } - if (!$namespace && strpos($this->as, '\\') === false) { + if (!$namespace && !str_contains($this->as, '\\')) { return 'class-string<' . $this->as . '>'; } diff --git a/src/Psalm/Type/Atomic/TClassStringMap.php b/src/Psalm/Type/Atomic/TClassStringMap.php index 028252540de..48c6d21d476 100644 --- a/src/Psalm/Type/Atomic/TClassStringMap.php +++ b/src/Psalm/Type/Atomic/TClassStringMap.php @@ -13,8 +13,6 @@ use Psalm\Type\Atomic; use Psalm\Type\Union; -use function get_class; - /** * Represents an array where the type of each value * is a function of its string key value @@ -23,24 +21,15 @@ */ final class TClassStringMap extends Atomic { - public string $param_name; - - public ?TNamedObject $as_type; - - public Union $value_param; - /** * Constructs a new instance of a list */ public function __construct( - string $param_name, - ?TNamedObject $as_type, - Union $value_param, + public string $param_name, + public ?TNamedObject $as_type, + public Union $value_param, bool $from_docblock = false, ) { - $this->param_name = $param_name; - $this->as_type = $as_type; - $this->value_param = $value_param; parent::__construct($from_docblock); } @@ -203,7 +192,7 @@ protected function getChildNodeKeys(): array public function equals(Atomic $other_type, bool $ensure_source_equality): bool { - if (get_class($other_type) !== static::class) { + if ($other_type::class !== self::class) { return false; } diff --git a/src/Psalm/Type/Atomic/TClosure.php b/src/Psalm/Type/Atomic/TClosure.php index b556f503d29..3f701c776c6 100644 --- a/src/Psalm/Type/Atomic/TClosure.php +++ b/src/Psalm/Type/Atomic/TClosure.php @@ -11,8 +11,6 @@ use Psalm\Type\Atomic; use Psalm\Type\Union; -use function array_merge; - /** * Represents a closure where we know the return type and params * @@ -22,9 +20,6 @@ final class TClosure extends TNamedObject { use CallableTrait; - /** @var array */ - public array $byref_uses = []; - /** * @param list $params * @param array $byref_uses @@ -35,14 +30,13 @@ public function __construct( ?array $params = null, ?Union $return_type = null, ?bool $is_pure = null, - array $byref_uses = [], + public array $byref_uses = [], array $extra_types = [], bool $from_docblock = false, ) { $this->params = $params; $this->return_type = $return_type; $this->is_pure = $is_pure; - $this->byref_uses = $byref_uses; parent::__construct( $value, false, @@ -133,6 +127,6 @@ public function replaceTemplateTypesWithStandins( protected function getChildNodeKeys(): array { - return array_merge(parent::getChildNodeKeys(), $this->getCallableChildNodeKeys()); + return [...parent::getChildNodeKeys(), ...$this->getCallableChildNodeKeys()]; } } diff --git a/src/Psalm/Type/Atomic/TConditional.php b/src/Psalm/Type/Atomic/TConditional.php index f15ebdf350e..4d6fc9f9afb 100644 --- a/src/Psalm/Type/Atomic/TConditional.php +++ b/src/Psalm/Type/Atomic/TConditional.php @@ -17,33 +17,15 @@ */ final class TConditional extends Atomic { - public string $param_name; - - public string $defining_class; - - public Union $as_type; - - public Union $conditional_type; - - public Union $if_type; - - public Union $else_type; - public function __construct( - string $param_name, - string $defining_class, - Union $as_type, - Union $conditional_type, - Union $if_type, - Union $else_type, + public string $param_name, + public string $defining_class, + public Union $as_type, + public Union $conditional_type, + public Union $if_type, + public Union $else_type, bool $from_docblock = false, ) { - $this->param_name = $param_name; - $this->defining_class = $defining_class; - $this->as_type = $as_type; - $this->conditional_type = $conditional_type; - $this->if_type = $if_type; - $this->else_type = $else_type; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TDependentGetClass.php b/src/Psalm/Type/Atomic/TDependentGetClass.php index ebc492233b0..3e6ab07329f 100644 --- a/src/Psalm/Type/Atomic/TDependentGetClass.php +++ b/src/Psalm/Type/Atomic/TDependentGetClass.php @@ -13,20 +13,11 @@ */ final class TDependentGetClass extends TString implements DependentType { - /** - * Used to hold information as to what this refers to - */ - public string $typeof; - - public Union $as_type; - /** * @param string $typeof the variable id */ - public function __construct(string $typeof, Union $as_type) + public function __construct(public string $typeof, public Union $as_type) { - $this->typeof = $typeof; - $this->as_type = $as_type; parent::__construct(false); } diff --git a/src/Psalm/Type/Atomic/TDependentGetDebugType.php b/src/Psalm/Type/Atomic/TDependentGetDebugType.php index 5875f911fdc..cddb12cdc6d 100644 --- a/src/Psalm/Type/Atomic/TDependentGetDebugType.php +++ b/src/Psalm/Type/Atomic/TDependentGetDebugType.php @@ -11,17 +11,11 @@ */ final class TDependentGetDebugType extends TString implements DependentType { - /** - * Used to hold information as to what this refers to - */ - public string $typeof; - /** * @param string $typeof the variable id */ - public function __construct(string $typeof) + public function __construct(public string $typeof) { - $this->typeof = $typeof; parent::__construct(false); } diff --git a/src/Psalm/Type/Atomic/TDependentGetType.php b/src/Psalm/Type/Atomic/TDependentGetType.php index 7f1bfee3877..a0d64d950f0 100644 --- a/src/Psalm/Type/Atomic/TDependentGetType.php +++ b/src/Psalm/Type/Atomic/TDependentGetType.php @@ -11,17 +11,11 @@ */ final class TDependentGetType extends TString { - /** - * Used to hold information as to what this refers to - */ - public string $typeof; - /** * @param string $typeof the variable id */ - public function __construct(string $typeof) + public function __construct(public string $typeof) { - $this->typeof = $typeof; parent::__construct(false); } diff --git a/src/Psalm/Type/Atomic/TEnumCase.php b/src/Psalm/Type/Atomic/TEnumCase.php index 2fcbb1faa69..99b5a8b99b3 100644 --- a/src/Psalm/Type/Atomic/TEnumCase.php +++ b/src/Psalm/Type/Atomic/TEnumCase.php @@ -11,13 +11,9 @@ */ final class TEnumCase extends TNamedObject { - public string $case_name; - - public function __construct(string $fq_enum_name, string $case_name) + public function __construct(string $fq_enum_name, public string $case_name) { parent::__construct($fq_enum_name); - - $this->case_name = $case_name; } public function getKey(bool $include_extra = true): string diff --git a/src/Psalm/Type/Atomic/TGenericObject.php b/src/Psalm/Type/Atomic/TGenericObject.php index 244a3218e40..9d5c3e3ea18 100644 --- a/src/Psalm/Type/Atomic/TGenericObject.php +++ b/src/Psalm/Type/Atomic/TGenericObject.php @@ -10,7 +10,6 @@ use Psalm\Type\Atomic; use Psalm\Type\Union; -use function array_merge; use function count; use function implode; use function strrpos; @@ -33,9 +32,6 @@ final class TGenericObject extends TNamedObject */ public array $type_params; - /** @var bool if the parameters have been remapped to another class */ - public bool $remapped_params = false; - /** * @param string $value the name of the object * @param non-empty-list $type_params @@ -44,7 +40,8 @@ final class TGenericObject extends TNamedObject public function __construct( string $value, array $type_params, - bool $remapped_params = false, + /** @var bool if the parameters have been remapped to another class */ + public bool $remapped_params = false, bool $is_static = false, array $extra_types = [], bool $from_docblock = false, @@ -54,7 +51,6 @@ public function __construct( } $this->type_params = $type_params; - $this->remapped_params = $remapped_params; parent::__construct( $value, $is_static, @@ -129,7 +125,7 @@ public function getAssertionString(): string protected function getChildNodeKeys(): array { - return array_merge(parent::getChildNodeKeys(), ['type_params']); + return [...parent::getChildNodeKeys(), 'type_params']; } /** diff --git a/src/Psalm/Type/Atomic/TIntMask.php b/src/Psalm/Type/Atomic/TIntMask.php index f19e30ee91d..6e753372c1f 100644 --- a/src/Psalm/Type/Atomic/TIntMask.php +++ b/src/Psalm/Type/Atomic/TIntMask.php @@ -14,13 +14,9 @@ */ final class TIntMask extends TInt { - /** @var non-empty-array */ - public array $values; - /** @param non-empty-array $values */ - public function __construct(array $values, bool $from_docblock = false) + public function __construct(public array $values, bool $from_docblock = false) { - $this->values = $values; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TIntMaskOf.php b/src/Psalm/Type/Atomic/TIntMaskOf.php index ace9727db82..398491c922b 100644 --- a/src/Psalm/Type/Atomic/TIntMaskOf.php +++ b/src/Psalm/Type/Atomic/TIntMaskOf.php @@ -4,8 +4,6 @@ namespace Psalm\Type\Atomic; -use Psalm\Type\Atomic; - /** * Represents the type that is the result of a bitmask combination of its parameters. * This is the same concept as TIntMask but TIntMaskOf is used with a reference to constants in code @@ -15,14 +13,8 @@ */ final class TIntMaskOf extends TInt { - public TClassConstant|TKeyOf|TValueOf $value; - - /** - * @param TClassConstant|TKeyOf|TValueOf $value - */ - public function __construct(Atomic $value, bool $from_docblock = false) + public function __construct(public TClassConstant|TKeyOf|TValueOf $value, bool $from_docblock = false) { - $this->value = $value; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TIntRange.php b/src/Psalm/Type/Atomic/TIntRange.php index b3a55d714fd..e7006a1c4f0 100644 --- a/src/Psalm/Type/Atomic/TIntRange.php +++ b/src/Psalm/Type/Atomic/TIntRange.php @@ -17,20 +17,12 @@ final class TIntRange extends TInt public const BOUND_MIN = 'min'; public const BOUND_MAX = 'max'; - public ?int $min_bound = null; - public ?int $max_bound = null; - - public ?string $dependent_list_key = null; - public function __construct( - ?int $min_bound, - ?int $max_bound, + public ?int $min_bound, + public ?int $max_bound, bool $from_docblock = false, - ?string $dependent_list_key = null, + public ?string $dependent_list_key = null, ) { - $this->min_bound = $min_bound; - $this->max_bound = $max_bound; - $this->dependent_list_key = $dependent_list_key; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TKeyOf.php b/src/Psalm/Type/Atomic/TKeyOf.php index 22d9e53d588..f8a259a7c76 100644 --- a/src/Psalm/Type/Atomic/TKeyOf.php +++ b/src/Psalm/Type/Atomic/TKeyOf.php @@ -16,11 +16,8 @@ */ final class TKeyOf extends TArrayKey { - public Union $type; - - public function __construct(Union $type, bool $from_docblock = false) + public function __construct(public Union $type, bool $from_docblock = false) { - $this->type = $type; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TKeyedArray.php b/src/Psalm/Type/Atomic/TKeyedArray.php index 80f9f968319..8547de17668 100644 --- a/src/Psalm/Type/Atomic/TKeyedArray.php +++ b/src/Psalm/Type/Atomic/TKeyedArray.php @@ -17,7 +17,6 @@ use function addslashes; use function assert; use function count; -use function get_class; use function implode; use function is_int; use function is_string; @@ -33,16 +32,6 @@ */ class TKeyedArray extends Atomic { - /** - * @var non-empty-array - */ - public array $properties; - - /** - * @var array|null - */ - public ?array $class_strings = null; - /** * If the shape has fallback params then they are here * @@ -68,8 +57,8 @@ class TKeyedArray extends Atomic * @param array $class_strings */ public function __construct( - array $properties, - ?array $class_strings = null, + public array $properties, + public ?array $class_strings = null, ?array $fallback_params = null, bool $is_list = false, bool $from_docblock = false, @@ -77,8 +66,6 @@ public function __construct( if ($is_list && $fallback_params) { $fallback_params[0] = Type::getListKey(); } - $this->properties = $properties; - $this->class_strings = $class_strings; $this->fallback_params = $fallback_params; $this->is_list = $is_list; if ($this->is_list) { @@ -646,7 +633,7 @@ protected function getChildNodeKeys(): array public function equals(Atomic $other_type, bool $ensure_source_equality): bool { - if (get_class($other_type) !== static::class) { + if ($other_type::class !== static::class) { return false; } diff --git a/src/Psalm/Type/Atomic/TLiteralClassString.php b/src/Psalm/Type/Atomic/TLiteralClassString.php index a3e14fa2d12..85bd43f2189 100644 --- a/src/Psalm/Type/Atomic/TLiteralClassString.php +++ b/src/Psalm/Type/Atomic/TLiteralClassString.php @@ -6,8 +6,8 @@ use function preg_quote; use function preg_replace; +use function str_contains; use function stripos; -use function strpos; use function strtolower; /** @@ -17,15 +17,14 @@ */ final class TLiteralClassString extends TLiteralString { - /** - * Whether or not this type can represent a child of the class named in $value - */ - public bool $definite_class = false; - - public function __construct(string $value, bool $definite_class = false, bool $from_docblock = false) - { + public function __construct( + string $value, /** + * Whether or not this type can represent a child of the class named in $value + */ + public bool $definite_class = false, + bool $from_docblock = false, + ) { parent::__construct($value, $from_docblock); - $this->definite_class = $definite_class; } public function getKey(bool $include_extra = true): string @@ -93,7 +92,7 @@ public function toNamespacedString( ) . '::class'; } - if (!$namespace && strpos($this->value, '\\') === false) { + if (!$namespace && !str_contains($this->value, '\\')) { return $this->value . '::class'; } diff --git a/src/Psalm/Type/Atomic/TLiteralFloat.php b/src/Psalm/Type/Atomic/TLiteralFloat.php index 3fe2a407269..1565183108b 100644 --- a/src/Psalm/Type/Atomic/TLiteralFloat.php +++ b/src/Psalm/Type/Atomic/TLiteralFloat.php @@ -11,11 +11,8 @@ */ final class TLiteralFloat extends TFloat { - public float $value; - - public function __construct(float $value, bool $from_docblock = false) + public function __construct(public float $value, bool $from_docblock = false) { - $this->value = $value; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TLiteralInt.php b/src/Psalm/Type/Atomic/TLiteralInt.php index 72706da25bc..ae28af3df30 100644 --- a/src/Psalm/Type/Atomic/TLiteralInt.php +++ b/src/Psalm/Type/Atomic/TLiteralInt.php @@ -11,11 +11,8 @@ */ final class TLiteralInt extends TInt { - public int $value; - - public function __construct(int $value, bool $from_docblock = false) + public function __construct(public int $value, bool $from_docblock = false) { - $this->value = $value; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TMixed.php b/src/Psalm/Type/Atomic/TMixed.php index b7f24fcb6c5..579c8a34737 100644 --- a/src/Psalm/Type/Atomic/TMixed.php +++ b/src/Psalm/Type/Atomic/TMixed.php @@ -13,11 +13,8 @@ */ class TMixed extends Atomic { - public bool $from_loop_isset = false; - - public function __construct(bool $from_loop_isset = false, bool $from_docblock = false) + public function __construct(public bool $from_loop_isset = false, bool $from_docblock = false) { - $this->from_loop_isset = $from_loop_isset; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TNamedObject.php b/src/Psalm/Type/Atomic/TNamedObject.php index 7a0a2e602fe..7d7e9a68c0f 100644 --- a/src/Psalm/Type/Atomic/TNamedObject.php +++ b/src/Psalm/Type/Atomic/TNamedObject.php @@ -26,23 +26,19 @@ class TNamedObject extends Atomic public string $value; - public bool $is_static = false; - public bool $is_static_resolved = false; - /** - * Whether or not this type can represent a child of the class named in $value - */ - public bool $definite_class = false; - /** * @param string $value the name of the object * @param array $extra_types */ public function __construct( string $value, - bool $is_static = false, - bool $definite_class = false, + public bool $is_static = false, + /** + * Whether or not this type can represent a child of the class named in $value + */ + public bool $definite_class = false, array $extra_types = [], bool $from_docblock = false, ) { @@ -51,8 +47,6 @@ public function __construct( } $this->value = $value; - $this->is_static = $is_static; - $this->definite_class = $definite_class; $this->extra_types = $extra_types; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TNonEmptyArray.php b/src/Psalm/Type/Atomic/TNonEmptyArray.php index b71dd5d5f3b..51767f30db1 100644 --- a/src/Psalm/Type/Atomic/TNonEmptyArray.php +++ b/src/Psalm/Type/Atomic/TNonEmptyArray.php @@ -14,18 +14,6 @@ */ final class TNonEmptyArray extends TArray { - /** - * @var positive-int|null - */ - public ?int $count = null; - - /** - * @var positive-int|null - */ - public ?int $min_count = null; - - public string $value = 'non-empty-array'; - /** * @param array{Union, Union} $type_params * @param positive-int|null $count @@ -33,14 +21,11 @@ final class TNonEmptyArray extends TArray */ public function __construct( array $type_params, - ?int $count = null, - ?int $min_count = null, - string $value = 'non-empty-array', + public ?int $count = null, + public ?int $min_count = null, + public string $value = 'non-empty-array', bool $from_docblock = false, ) { - $this->count = $count; - $this->min_count = $min_count; - $this->value = $value; parent::__construct($type_params, $from_docblock); } diff --git a/src/Psalm/Type/Atomic/TObjectWithProperties.php b/src/Psalm/Type/Atomic/TObjectWithProperties.php index 1f54c63c8a8..95736e0e4c5 100644 --- a/src/Psalm/Type/Atomic/TObjectWithProperties.php +++ b/src/Psalm/Type/Atomic/TObjectWithProperties.php @@ -26,16 +26,6 @@ final class TObjectWithProperties extends TObject { use HasIntersectionTrait; - /** - * @var array - */ - public array $properties; - - /** - * @var array - */ - public array $methods; - public bool $is_stringable_object_only = false; /** @@ -46,13 +36,11 @@ final class TObjectWithProperties extends TObject * @param array $extra_types */ public function __construct( - array $properties, - array $methods = [], + public array $properties, + public array $methods = [], array $extra_types = [], bool $from_docblock = false, ) { - $this->properties = $properties; - $this->methods = $methods; $this->extra_types = $extra_types; $this->is_stringable_object_only = diff --git a/src/Psalm/Type/Atomic/TPropertiesOf.php b/src/Psalm/Type/Atomic/TPropertiesOf.php index c5c4a92b6fe..7724143c1b9 100644 --- a/src/Psalm/Type/Atomic/TPropertiesOf.php +++ b/src/Psalm/Type/Atomic/TPropertiesOf.php @@ -22,12 +22,6 @@ final class TPropertiesOf extends Atomic public const VISIBILITY_PROTECTED = 2; public const VISIBILITY_PRIVATE = 3; - public TNamedObject $classlike_type; - /** - * @var self::VISIBILITY_*|null - */ - public ?int $visibility_filter; - /** * @return list */ @@ -45,12 +39,10 @@ public static function tokenNames(): array * @param self::VISIBILITY_*|null $visibility_filter */ public function __construct( - TNamedObject $classlike_type, - ?int $visibility_filter, + public TNamedObject $classlike_type, + public ?int $visibility_filter, bool $from_docblock = false, ) { - $this->classlike_type = $classlike_type; - $this->visibility_filter = $visibility_filter; parent::__construct($from_docblock); } @@ -59,16 +51,12 @@ public function __construct( */ public static function filterForTokenName(string $token_name): ?int { - switch ($token_name) { - case 'public-properties-of': - return self::VISIBILITY_PUBLIC; - case 'protected-properties-of': - return self::VISIBILITY_PROTECTED; - case 'private-properties-of': - return self::VISIBILITY_PRIVATE; - default: - return null; - } + return match ($token_name) { + 'public-properties-of' => self::VISIBILITY_PUBLIC, + 'protected-properties-of' => self::VISIBILITY_PROTECTED, + 'private-properties-of' => self::VISIBILITY_PRIVATE, + default => null, + }; } /** @@ -77,16 +65,12 @@ public static function filterForTokenName(string $token_name): ?int */ public static function tokenNameForFilter(?int $visibility_filter): string { - switch ($visibility_filter) { - case self::VISIBILITY_PUBLIC: - return 'public-properties-of'; - case self::VISIBILITY_PROTECTED: - return 'protected-properties-of'; - case self::VISIBILITY_PRIVATE: - return 'private-properties-of'; - default: - return 'properties-of'; - } + return match ($visibility_filter) { + self::VISIBILITY_PUBLIC => 'public-properties-of', + self::VISIBILITY_PROTECTED => 'protected-properties-of', + self::VISIBILITY_PRIVATE => 'private-properties-of', + default => 'properties-of', + }; } protected function getChildNodeKeys(): array diff --git a/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php b/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php index bba86e66e29..c572c185234 100644 --- a/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php +++ b/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php @@ -11,21 +11,12 @@ */ final class TTemplateIndexedAccess extends Atomic { - public string $array_param_name; - - public string $offset_param_name; - - public string $defining_class; - public function __construct( - string $array_param_name, - string $offset_param_name, - string $defining_class, + public string $array_param_name, + public string $offset_param_name, + public string $defining_class, bool $from_docblock = false, ) { - $this->array_param_name = $array_param_name; - $this->offset_param_name = $offset_param_name; - $this->defining_class = $defining_class; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TTemplateKeyOf.php b/src/Psalm/Type/Atomic/TTemplateKeyOf.php index 48c61dff5ec..4773dc9d4df 100644 --- a/src/Psalm/Type/Atomic/TTemplateKeyOf.php +++ b/src/Psalm/Type/Atomic/TTemplateKeyOf.php @@ -17,21 +17,12 @@ */ final class TTemplateKeyOf extends Atomic { - public string $param_name; - - public string $defining_class; - - public Union $as; - public function __construct( - string $param_name, - string $defining_class, - Union $as, + public string $param_name, + public string $defining_class, + public Union $as, bool $from_docblock = false, ) { - $this->param_name = $param_name; - $this->defining_class = $defining_class; - $this->as = $as; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TTemplateParam.php b/src/Psalm/Type/Atomic/TTemplateParam.php index 8a95ab2bdb8..9f618b3090b 100644 --- a/src/Psalm/Type/Atomic/TTemplateParam.php +++ b/src/Psalm/Type/Atomic/TTemplateParam.php @@ -21,25 +21,16 @@ final class TTemplateParam extends Atomic { use HasIntersectionTrait; - public string $param_name; - - public Union $as; - - public string $defining_class; - /** * @param array $extra_types */ public function __construct( - string $param_name, - Union $extends, - string $defining_class, + public string $param_name, + public Union $as, + public string $defining_class, array $extra_types = [], bool $from_docblock = false, ) { - $this->param_name = $param_name; - $this->as = $extends; - $this->defining_class = $defining_class; $this->extra_types = $extra_types; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TTemplateParamClass.php b/src/Psalm/Type/Atomic/TTemplateParamClass.php index 00b370a68b8..8bbbf7f3769 100644 --- a/src/Psalm/Type/Atomic/TTemplateParamClass.php +++ b/src/Psalm/Type/Atomic/TTemplateParamClass.php @@ -11,19 +11,13 @@ */ final class TTemplateParamClass extends TClassString { - public string $param_name; - - public string $defining_class; - public function __construct( - string $param_name, + public string $param_name, string $as, ?TNamedObject $as_type, - string $defining_class, + public string $defining_class, bool $from_docblock = false, ) { - $this->param_name = $param_name; - $this->defining_class = $defining_class; parent::__construct( $as, $as_type, diff --git a/src/Psalm/Type/Atomic/TTemplatePropertiesOf.php b/src/Psalm/Type/Atomic/TTemplatePropertiesOf.php index 31f6ef3b3ec..4efe92a602a 100644 --- a/src/Psalm/Type/Atomic/TTemplatePropertiesOf.php +++ b/src/Psalm/Type/Atomic/TTemplatePropertiesOf.php @@ -17,28 +17,16 @@ */ final class TTemplatePropertiesOf extends Atomic { - public string $param_name; - public string $defining_class; - public TTemplateParam $as; - /** - * @var TPropertiesOf::VISIBILITY_*|null - */ - public ?int $visibility_filter; - /** * @param TPropertiesOf::VISIBILITY_*|null $visibility_filter */ public function __construct( - string $param_name, - string $defining_class, - TTemplateParam $as, - ?int $visibility_filter, + public string $param_name, + public string $defining_class, + public TTemplateParam $as, + public ?int $visibility_filter, bool $from_docblock = false, ) { - $this->param_name = $param_name; - $this->defining_class = $defining_class; - $this->as = $as; - $this->visibility_filter = $visibility_filter; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TTemplateValueOf.php b/src/Psalm/Type/Atomic/TTemplateValueOf.php index 98be9d1e85c..583d079578b 100644 --- a/src/Psalm/Type/Atomic/TTemplateValueOf.php +++ b/src/Psalm/Type/Atomic/TTemplateValueOf.php @@ -17,21 +17,12 @@ */ final class TTemplateValueOf extends Atomic { - public string $param_name; - - public string $defining_class; - - public Union $as; - public function __construct( - string $param_name, - string $defining_class, - Union $as, + public string $param_name, + public string $defining_class, + public Union $as, bool $from_docblock = false, ) { - $this->param_name = $param_name; - $this->defining_class = $defining_class; - $this->as = $as; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/Atomic/TTypeAlias.php b/src/Psalm/Type/Atomic/TTypeAlias.php index 52a2fe9037a..f9c27297607 100644 --- a/src/Psalm/Type/Atomic/TTypeAlias.php +++ b/src/Psalm/Type/Atomic/TTypeAlias.php @@ -14,27 +14,18 @@ */ final class TTypeAlias extends Atomic { - /** - * @var array|null - * @deprecated type aliases are resolved within {@see TypeParser::resolveTypeAliases()} and therefore the - * referencing type(s) are part of other intersection types. The intersection types are not set anymore - * and with v6 this property along with its related methods will get removed. - */ - public ?array $extra_types = null; - - public string $declaring_fq_classlike_name; - - public string $alias_name; - /** * @param array|null $extra_types */ - public function __construct(string $declaring_fq_classlike_name, string $alias_name, ?array $extra_types = null) - { - $this->declaring_fq_classlike_name = $declaring_fq_classlike_name; - $this->alias_name = $alias_name; - /** @psalm-suppress DeprecatedProperty For backwards compatibility, we have to keep this here. */ - $this->extra_types = $extra_types; + public function __construct( + public string $declaring_fq_classlike_name, + public string $alias_name, /** + * @deprecated type aliases are resolved within {@see TypeParser::resolveTypeAliases()} and therefore the + * referencing type(s) are part of other intersection types. The intersection types are not set anymore + * and with v6 this property along with its related methods will get removed. + */ + public ?array $extra_types = null, + ) { parent::__construct(true); } /** diff --git a/src/Psalm/Type/Atomic/TUnknownClassString.php b/src/Psalm/Type/Atomic/TUnknownClassString.php index a8d2811e0cc..c46cf16c2b5 100644 --- a/src/Psalm/Type/Atomic/TUnknownClassString.php +++ b/src/Psalm/Type/Atomic/TUnknownClassString.php @@ -12,10 +12,8 @@ */ final class TUnknownClassString extends TClassString { - public ?TObject $as_unknown_type; - public function __construct( - ?TObject $as_unknown_type, + public ?TObject $as_unknown_type, bool $is_loaded = false, bool $from_docblock = false, ) { @@ -27,6 +25,5 @@ public function __construct( false, $from_docblock, ); - $this->as_unknown_type = $as_unknown_type; } } diff --git a/src/Psalm/Type/Atomic/TValueOf.php b/src/Psalm/Type/Atomic/TValueOf.php index ad71cd03ce3..71afca107e3 100644 --- a/src/Psalm/Type/Atomic/TValueOf.php +++ b/src/Psalm/Type/Atomic/TValueOf.php @@ -20,11 +20,8 @@ */ final class TValueOf extends Atomic { - public Union $type; - - public function __construct(Union $type, bool $from_docblock = false) + public function __construct(public Union $type, bool $from_docblock = false) { - $this->type = $type; parent::__construct($from_docblock); } diff --git a/src/Psalm/Type/MutableUnion.php b/src/Psalm/Type/MutableUnion.php index 70b6377ee69..b5f42645fe7 100644 --- a/src/Psalm/Type/MutableUnion.php +++ b/src/Psalm/Type/MutableUnion.php @@ -26,7 +26,6 @@ use Psalm\Type\Atomic\TTrue; use function count; -use function get_class; use function get_object_vars; use function strpos; @@ -409,7 +408,7 @@ public function substitute(Union|MutableUnion $old_type, Union|MutableUnion|null foreach ($new_type->types as $key => $new_type_part) { if (!isset($this->types[$key]) || ($new_type_part instanceof Scalar - && get_class($new_type_part) === get_class($this->types[$key])) + && $new_type_part::class === $this->types[$key]::class) ) { $this->types[$key] = $new_type_part; } else { diff --git a/src/Psalm/Type/Reconciler.php b/src/Psalm/Type/Reconciler.php index 6cc30cdc79f..ae321e5f2f1 100644 --- a/src/Psalm/Type/Reconciler.php +++ b/src/Psalm/Type/Reconciler.php @@ -69,6 +69,8 @@ use function ksort; use function preg_match; use function preg_quote; +use function str_contains; +use function str_ends_with; use function str_replace; use function str_split; use function strlen; @@ -330,7 +332,7 @@ public static function reconcileKeyedTypes( if ($type_changed || $failed_reconciliation) { $changed_var_ids[$key] = true; - if (substr($key, -1) === ']' && !$has_inverted_isset && !$has_empty && !$is_equality) { + if (str_ends_with($key, ']') && !$has_inverted_isset && !$has_empty && !$is_equality) { self::adjustTKeyedArrayType( $key_parts, $existing_types, @@ -344,7 +346,7 @@ public static function reconcileKeyedTypes( } if (!isset($new_types[$new_key]) - && preg_match('/' . preg_quote($key, '/') . '[\]\[\-]/', $new_key) + && preg_match('/' . preg_quote($key, '/') . '[\]\[\-]/', (string) $new_key) && $is_real ) { // Fix any references to the type before removing it. @@ -459,7 +461,7 @@ private static function addNestedAssertions(array $new_types, array $existing_ty $new_base_key = $base_key . '[' . $array_key . ']'; - if (strpos($array_key, '\'') !== false) { + if (str_contains($array_key, '\'')) { $new_types[$base_key][] = [new HasStringArrayAccess()]; } else { $new_types[$base_key][] = [new HasIntOrStringArrayAccess()]; @@ -822,7 +824,7 @@ private static function getValueForKey( if (!$codebase->classOrInterfaceExists($existing_key_type_part->value)) { $class_property_type = Type::getMixed(); } else { - if (substr($property_name, -2) === '()') { + if (str_ends_with($property_name, '()')) { $method_id = new MethodIdentifier( $existing_key_type_part->value, strtolower(substr($property_name, 0, -2)), @@ -920,11 +922,7 @@ private static function getPropertyType( $fq_class_name, ); - if (isset($declaring_class_storage->pseudo_property_get_types['$' . $property_name])) { - return $declaring_class_storage->pseudo_property_get_types['$' . $property_name]; - } - - return null; + return $declaring_class_storage->pseudo_property_get_types['$' . $property_name] ?? null; } $declaring_property_class = $codebase->properties->getDeclaringClassForProperty( diff --git a/src/Psalm/Type/Union.php b/src/Psalm/Type/Union.php index 1d0b7fd0748..49dc6c90371 100644 --- a/src/Psalm/Type/Union.php +++ b/src/Psalm/Type/Union.php @@ -176,7 +176,7 @@ final class Union implements TypeNode /** * This is a cache of getId on exact mode */ - private ?string $exact_id; + private ?string $exact_id = null; /** diff --git a/src/Psalm/Type/UnionTrait.php b/src/Psalm/Type/UnionTrait.php index 8ae3600764e..ad08a02b20a 100644 --- a/src/Psalm/Type/UnionTrait.php +++ b/src/Psalm/Type/UnionTrait.php @@ -44,14 +44,13 @@ use Psalm\Type\Atomic\TTrue; use function array_filter; -use function array_merge; use function array_unique; use function count; -use function get_class; use function implode; use function ksort; use function reset; use function sort; +use function str_contains; use function strpos; use const ARRAY_FILTER_USE_BOTH; @@ -220,7 +219,7 @@ public function getId(bool $exact = true): string if (count($types) > 1) { foreach ($types as $i => $type) { - if (strpos($type, ' as ') && strpos($type, '(') === false) { + if (strpos((string) $type, ' as ') && !str_contains((string) $type, '(')) { $types[$i] = '(' . $type . ')'; } } @@ -264,9 +263,9 @@ public function toNamespacedString( } elseif ($type instanceof TLiteralString) { $literal_strings[] = $type_string; } else { - if (get_class($type) === TString::class) { + if ($type::class === TString::class) { $has_non_literal_string = true; - } elseif (get_class($type) === TInt::class) { + } elseif ($type::class === TInt::class) { $has_non_literal_int = true; } $other_types[] = $type_string; @@ -274,13 +273,13 @@ public function toNamespacedString( } if (count($literal_ints) <= 3 && !$has_non_literal_int) { - $other_types = array_merge($other_types, $literal_ints); + $other_types = [...$other_types, ...$literal_ints]; } else { $other_types[] = 'int'; } if (count($literal_strings) <= 3 && !$has_non_literal_string) { - $other_types = array_merge($other_types, $literal_strings); + $other_types = [...$other_types, ...$literal_strings]; } else { $other_types[] = 'string'; } @@ -828,7 +827,7 @@ public function isEmptyMixed(): bool public function isVanillaMixed(): bool { return isset($this->types['mixed']) - && get_class($this->types['mixed']) === TMixed::class + && $this->types['mixed']::class === TMixed::class && !$this->types['mixed']->from_loop_isset && count($this->types) === 1; } diff --git a/tests/AsyncTestCase.php b/tests/AsyncTestCase.php index 0e89d76594e..fba4d2f85e0 100644 --- a/tests/AsyncTestCase.php +++ b/tests/AsyncTestCase.php @@ -154,7 +154,7 @@ public static function assertArrayKeysAreStrings(array $array, string $message = */ public static function assertArrayKeysAreZeroOrString(array $array, string $message = ''): void { - $isZeroOrString = /** @param mixed $key */ fn($key): bool => $key === 0 || is_string($key); + $isZeroOrString = /** @param mixed $key */ fn(mixed $key): bool => $key === 0 || is_string($key); $validKeys = array_filter($array, $isZeroOrString, ARRAY_FILTER_USE_KEY); self::assertTrue(count($array) === count($validKeys), $message); } @@ -190,7 +190,7 @@ public static function assertStringIsParsableType(string $type, string $message try { $tokens = TypeTokenizer::tokenize($type); $union = TypeParser::parseTokens($tokens); - } catch (Throwable $_e) { + } catch (Throwable) { } self::assertInstanceOf(Union::class, $union, $message); } diff --git a/tests/BinaryOperationTest.php b/tests/BinaryOperationTest.php index 094f1bbe09c..0b948d53587 100644 --- a/tests/BinaryOperationTest.php +++ b/tests/BinaryOperationTest.php @@ -4,6 +4,7 @@ namespace Psalm\Tests; +use Decimal\Decimal; use Psalm\Config; use Psalm\Context; use Psalm\Exception\CodeException; @@ -112,25 +113,25 @@ public function testDecimalOperations(): void ); $assertions = [ - '$a' => 'Decimal\\Decimal', - '$b' => 'Decimal\\Decimal', - '$c' => 'Decimal\\Decimal', - '$d' => 'Decimal\\Decimal', - '$f' => 'Decimal\\Decimal', - '$g' => 'Decimal\\Decimal', - '$h' => 'Decimal\\Decimal', - '$i' => 'Decimal\\Decimal', - '$j' => 'Decimal\\Decimal', - '$k' => 'Decimal\\Decimal', - '$l' => 'Decimal\\Decimal', - '$m' => 'Decimal\\Decimal', - '$n' => 'Decimal\\Decimal', - '$o' => 'Decimal\\Decimal', - '$p' => 'Decimal\\Decimal', - '$q' => 'Decimal\\Decimal', - '$r' => 'Decimal\\Decimal', - '$s' => 'Decimal\\Decimal', - '$t' => 'Decimal\\Decimal', + '$a' => Decimal::class, + '$b' => Decimal::class, + '$c' => Decimal::class, + '$d' => Decimal::class, + '$f' => Decimal::class, + '$g' => Decimal::class, + '$h' => Decimal::class, + '$i' => Decimal::class, + '$j' => Decimal::class, + '$k' => Decimal::class, + '$l' => Decimal::class, + '$m' => Decimal::class, + '$n' => Decimal::class, + '$o' => Decimal::class, + '$p' => Decimal::class, + '$q' => Decimal::class, + '$r' => Decimal::class, + '$s' => Decimal::class, + '$t' => Decimal::class, ]; $context = new Context(); diff --git a/tests/CodebaseTest.php b/tests/CodebaseTest.php index 0a176430798..f6230620651 100644 --- a/tests/CodebaseTest.php +++ b/tests/CodebaseTest.php @@ -22,7 +22,6 @@ use function array_map; use function array_values; -use function get_class; class CodebaseTest extends TestCase { @@ -173,7 +172,7 @@ public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event) } }; (new PluginRegistrationSocket($this->codebase->config, $this->codebase)) - ->registerHooksFromClass(get_class($hook)); + ->registerHooksFromClass($hook::class); $this->codebase->classlike_storage_provider->cache = new ClassLikeStorageInstanceCacheProvider; $this->analyzeFile('somefile.php', new Context); @@ -243,7 +242,7 @@ public static function beforeAddIssue(BeforeAddIssueEvent $event): ?bool }; (new PluginRegistrationSocket($this->codebase->config, $this->codebase)) - ->registerHooksFromClass(get_class($eventHandler)); + ->registerHooksFromClass($eventHandler::class); $this->analyzeFile('somefile.php', new Context); self::assertSame(0, IssueBuffer::getErrorCount()); diff --git a/tests/Config/ConfigTest.php b/tests/Config/ConfigTest.php index 9fa8042c55c..484738e8c46 100644 --- a/tests/Config/ConfigTest.php +++ b/tests/Config/ConfigTest.php @@ -31,7 +31,6 @@ use function defined; use function dirname; use function error_get_last; -use function get_class; use function getcwd; use function implode; use function in_array; @@ -1728,8 +1727,8 @@ public function pluginRegistersScannerAndAnalyzer(int $flags, ?int $expectedExce } self::assertContains($extension, $config->getFileExtensions()); - self::assertSame(get_class($scannerMock), $config->getFiletypeScanners()[$extension] ?? null); - self::assertSame(get_class($analyzerMock), $config->getFiletypeAnalyzers()[$extension] ?? null); + self::assertSame($scannerMock::class, $config->getFiletypeScanners()[$extension] ?? null); + self::assertSame($analyzerMock::class, $config->getFiletypeAnalyzers()[$extension] ?? null); self::assertNull($expectedExceptionCode, 'Expected exception code was not thrown'); } diff --git a/tests/Config/Plugin/FileTypeSelfRegisteringPlugin.php b/tests/Config/Plugin/FileTypeSelfRegisteringPlugin.php index e9df9433663..24f51ccf10d 100644 --- a/tests/Config/Plugin/FileTypeSelfRegisteringPlugin.php +++ b/tests/Config/Plugin/FileTypeSelfRegisteringPlugin.php @@ -11,11 +11,11 @@ class FileTypeSelfRegisteringPlugin implements PluginFileExtensionsInterface { - public const FLAG_SCANNER_TWICE = 1; - public const FLAG_ANALYZER_TWICE = 2; + final public const FLAG_SCANNER_TWICE = 1; + final public const FLAG_ANALYZER_TWICE = 2; - public const FLAG_SCANNER_INVALID = 4; - public const FLAG_ANALYZER_INVALID = 8; + final public const FLAG_SCANNER_INVALID = 4; + final public const FLAG_ANALYZER_INVALID = 8; /** * @var array diff --git a/tests/Config/PluginTest.php b/tests/Config/PluginTest.php index 93f2eb95bb3..15b71ce980c 100644 --- a/tests/Config/PluginTest.php +++ b/tests/Config/PluginTest.php @@ -30,7 +30,6 @@ use function define; use function defined; use function dirname; -use function get_class; use function getcwd; use function microtime; use function ob_end_clean; @@ -506,10 +505,10 @@ public static function afterCodebasePopulated(AfterCodebasePopulatedEvent $event $config = $codebase->config; - (new PluginRegistrationSocket($config, $codebase))->registerHooksFromClass(get_class($hook)); + (new PluginRegistrationSocket($config, $codebase))->registerHooksFromClass($hook::class); $this->assertContains( - get_class($hook), + $hook::class, $this->project_analyzer->getCodebase()->config->eventDispatcher->after_codebase_populated, ); } @@ -888,7 +887,7 @@ public static function afterEveryFunctionCallAnalysis(AfterEveryFunctionCallAnal }; $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); - $this->project_analyzer->getCodebase()->config->eventDispatcher->after_every_function_checks[] = get_class($plugin); + $this->project_analyzer->getCodebase()->config->eventDispatcher->after_every_function_checks[] = $plugin::class; $file_path = (string) getcwd() . '/src/somefile.php'; diff --git a/tests/ConstantTest.php b/tests/ConstantTest.php index bc0ec6404c0..dabad76e615 100644 --- a/tests/ConstantTest.php +++ b/tests/ConstantTest.php @@ -1875,20 +1875,21 @@ class B PHP, ], 'maxIntegerInArrayKey' => [ - 'code' => <<<'PHP' - 1]; - public const I = [9223372036854775807 => 1]; + 'code' => <<<'PHP_WRAP' + 1]; + public const I = [9223372036854775807 => 1]; - // PHP_INT_MAX + 1 - public const SO = ['9223372036854775808' => 1]; - } - $s = A::S; - $i = A::I; - $so = A::SO; - PHP, + // PHP_INT_MAX + 1 + public const SO = ['9223372036854775808' => 1]; +} +$s = A::S; +$i = A::I; +$so = A::SO; +PHP_WRAP +, 'assertions' => [ '$s===' => 'array{9223372036854775807: 1}', '$i===' => 'array{9223372036854775807: 1}', @@ -1896,16 +1897,17 @@ class A { ], ], 'autoincrementAlmostOverflow' => [ - 'code' => <<<'PHP' - 0, - 1, // expected key = PHP_INT_MAX - ]; - } - $s = A::I; - PHP, + 'code' => <<<'PHP_WRAP' + 0, + 1, // expected key = PHP_INT_MAX + ]; +} +$s = A::I; +PHP_WRAP +, 'assertions' => [ '$s===' => 'array{9223372036854775806: 0, 9223372036854775807: 1}', ], @@ -2445,13 +2447,14 @@ class Foo { 'error_message' => 'InvalidStringClass', ], 'integerOverflowInArrayKey' => [ - 'code' => <<<'PHP' - 1]; - } - PHP, + 'code' => <<<'PHP_WRAP' + 1]; +} +PHP_WRAP +, 'error_message' => 'InvalidArrayOffset', ], 'autoincrementOverflow' => [ diff --git a/tests/DocumentationTest.php b/tests/DocumentationTest.php index 9768eecfa83..d6b8d754302 100644 --- a/tests/DocumentationTest.php +++ b/tests/DocumentationTest.php @@ -40,7 +40,9 @@ use function preg_quote; use function scandir; use function sort; +use function str_contains; use function str_replace; +use function str_starts_with; use function strlen; use function strpos; use function substr; @@ -117,14 +119,14 @@ private static function getCodeBlocksFromDocs(): array for ($i = 0, $j = count($file_lines); $i < $j; ++$i) { $current_line = $file_lines[$i]; - if (substr($current_line, 0, 6) === '```php' && $current_issue) { + if (str_starts_with($current_line, '```php') && $current_issue) { $current_block = ''; ++$i; do { $current_block .= $file_lines[$i] . "\n"; ++$i; - } while (substr($file_lines[$i], 0, 3) !== '```' && $i < $j); + } while (!str_starts_with($file_lines[$i], '```') && $i < $j); $issue_code[$current_issue][] = trim($current_block); @@ -209,7 +211,7 @@ public function testAllIssuesCovered(): void */ public function testInvalidCode(string $code, string $error_message, array $ignored_issues = [], bool $check_references = false, string $php_version = '8.0'): void { - if (strpos($this->getTestName(), 'SKIPPED-') !== false) { + if (str_contains($this->getTestName(), 'SKIPPED-')) { $this->markTestSkipped(); } @@ -220,9 +222,9 @@ public function testInvalidCode(string $code, string $error_message, array $igno $this->project_analyzer->trackUnusedSuppressions(); } - $is_taint_test = strpos($error_message, 'Tainted') !== false; + $is_taint_test = str_contains($error_message, 'Tainted'); - $is_array_offset_test = strpos($error_message, 'ArrayOffset') && strpos($error_message, 'PossiblyUndefined') !== false; + $is_array_offset_test = strpos($error_message, 'ArrayOffset') && str_contains($error_message, 'PossiblyUndefined'); $this->project_analyzer->getConfig()->ensure_array_string_offsets_exist = $is_array_offset_test; $this->project_analyzer->getConfig()->ensure_array_int_offsets_exist = $is_array_offset_test; @@ -323,9 +325,9 @@ public function providerInvalidCodeParse(): array $blocks[0], $issue_name, $ignored_issues, - strpos($issue_name, 'Unused') !== false - || strpos($issue_name, 'Unevaluated') !== false - || strpos($issue_name, 'Unnecessary') !== false, + str_contains($issue_name, 'Unused') + || str_contains($issue_name, 'Unevaluated') + || str_contains($issue_name, 'Unnecessary'), $php_version, ]; } @@ -399,11 +401,8 @@ public function conciseExpected(Constraint $inner): Constraint { return new class ($inner) extends Constraint { - private Constraint $inner; - - public function __construct(Constraint $inner) + public function __construct(private readonly Constraint $inner) { - $this->inner = $inner; } public function toString(): string diff --git a/tests/ExpressionTest.php b/tests/ExpressionTest.php index 15fb517c116..ae4b4067871 100644 --- a/tests/ExpressionTest.php +++ b/tests/ExpressionTest.php @@ -26,15 +26,16 @@ class ExpressionTest extends TestCase public function providerValidCodeParse(): iterable { yield 'maxIntegerInArrayKey' => [ - 'code' => <<<'PHP' - 1]; - $i = [9223372036854775807 => 1]; + 'code' => <<<'PHP_WRAP' + 1]; +$i = [9223372036854775807 => 1]; - // PHP_INT_MAX + 1 - $so = ['9223372036854775808' => 1]; - PHP, +// PHP_INT_MAX + 1 +$so = ['9223372036854775808' => 1]; +PHP_WRAP +, 'assertions' => [ '$s===' => 'array{9223372036854775807: 1}', '$i===' => 'array{9223372036854775807: 1}', @@ -42,13 +43,14 @@ public function providerValidCodeParse(): iterable ], ]; yield 'autoincrementAlmostOverflow' => [ - 'code' => <<<'PHP' - 0, - 1, // expected key = PHP_INT_MAX - ]; - PHP, + 'code' => <<<'PHP_WRAP' + 0, + 1, // expected key = PHP_INT_MAX +]; +PHP_WRAP +, 'assertions' => [ '$a===' => 'array{9223372036854775806: 0, 9223372036854775807: 1}', ], @@ -69,11 +71,12 @@ public function providerValidCodeParse(): iterable public function providerInvalidCodeParse(): iterable { yield 'integerOverflowInArrayKey' => [ - 'code' => <<<'PHP' - 1]; - PHP, + 'code' => <<<'PHP_WRAP' + 1]; +PHP_WRAP +, 'error_message' => 'InvalidArrayOffset', ]; diff --git a/tests/FileDiffTest.php b/tests/FileDiffTest.php index 0e7982552b9..5bea1b86aab 100644 --- a/tests/FileDiffTest.php +++ b/tests/FileDiffTest.php @@ -12,8 +12,7 @@ use function array_map; use function count; -use function get_class; -use function strpos; +use function str_contains; use function var_export; class FileDiffTest extends TestCase @@ -31,7 +30,7 @@ public function testCode( array $diff_map_offsets, array $deletion_ranges, ): void { - if (strpos($this->getTestName(), 'SKIPPED-') !== false) { + if (str_contains($this->getTestName(), 'SKIPPED-')) { $this->markTestSkipped(); } @@ -88,7 +87,7 @@ public function testPartialAstDiff( array $changed_methods, array $diff_map_offsets, ): void { - if (strpos($this->getTestName(), 'SKIPPED-') !== false) { + if (str_contains($this->getTestName(), 'SKIPPED-')) { $this->markTestSkipped(); } @@ -155,12 +154,12 @@ private function assertTreesEqual(array $a, array $b): void $this->assertNotSame($a_stmt, $b_stmt); - $this->assertSame(get_class($a_stmt), get_class($b_stmt)); + $this->assertSame($a_stmt::class, $b_stmt::class); if ($a_stmt instanceof PhpParser\Node\Stmt\Expression && $b_stmt instanceof PhpParser\Node\Stmt\Expression ) { - $this->assertSame(get_class($a_stmt->expr), get_class($b_stmt->expr)); + $this->assertSame($a_stmt->expr::class, $b_stmt->expr::class); } if ($a_doc = $a_stmt->getDocComment()) { @@ -181,8 +180,8 @@ private function assertTreesEqual(array $a, array $b): void $a_stmt->getAttribute('endFilePos'), $b_stmt->getAttribute('endFilePos'), ($a_stmt instanceof PhpParser\Node\Stmt\Expression - ? get_class($a_stmt->expr) - : get_class($a_stmt)) + ? $a_stmt->expr::class + : $a_stmt::class) . ' on line ' . $a_stmt->getLine(), ); $this->assertSame($a_stmt->getLine(), $b_stmt->getLine()); diff --git a/tests/FileManipulation/ClassConstantMoveTest.php b/tests/FileManipulation/ClassConstantMoveTest.php index 3e22aa14a0b..fd91a345030 100644 --- a/tests/FileManipulation/ClassConstantMoveTest.php +++ b/tests/FileManipulation/ClassConstantMoveTest.php @@ -13,7 +13,7 @@ use Psalm\Tests\TestCase; use Psalm\Tests\TestConfig; -use function strpos; +use function str_contains; class ClassConstantMoveTest extends TestCase { @@ -36,7 +36,7 @@ public function testValidCode( array $constants_to_move, ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/ClassMoveTest.php b/tests/FileManipulation/ClassMoveTest.php index c2f5c8ee7a5..20185e5abe8 100644 --- a/tests/FileManipulation/ClassMoveTest.php +++ b/tests/FileManipulation/ClassMoveTest.php @@ -13,7 +13,7 @@ use Psalm\Tests\TestCase; use Psalm\Tests\TestConfig; -use function strpos; +use function str_contains; class ClassMoveTest extends TestCase { @@ -36,7 +36,7 @@ public function testValidCode( array $constants_to_move, ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/FileManipulationTestCase.php b/tests/FileManipulation/FileManipulationTestCase.php index 06941283881..b681052cc86 100644 --- a/tests/FileManipulation/FileManipulationTestCase.php +++ b/tests/FileManipulation/FileManipulationTestCase.php @@ -13,6 +13,7 @@ use Psalm\Tests\TestCase; use Psalm\Tests\TestConfig; +use function str_contains; use function strpos; abstract class FileManipulationTestCase extends TestCase @@ -39,7 +40,7 @@ public function testValidCode( bool $allow_backwards_incompatible_changes = true, ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/MethodMoveTest.php b/tests/FileManipulation/MethodMoveTest.php index 51c9b18dc6b..32abe8dd1e6 100644 --- a/tests/FileManipulation/MethodMoveTest.php +++ b/tests/FileManipulation/MethodMoveTest.php @@ -13,7 +13,7 @@ use Psalm\Tests\TestCase; use Psalm\Tests\TestConfig; -use function strpos; +use function str_contains; class MethodMoveTest extends TestCase { @@ -36,7 +36,7 @@ public function testValidCode( array $methods_to_move, ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/NamespaceMoveTest.php b/tests/FileManipulation/NamespaceMoveTest.php index 537d20b836c..1f3177ad35a 100644 --- a/tests/FileManipulation/NamespaceMoveTest.php +++ b/tests/FileManipulation/NamespaceMoveTest.php @@ -13,7 +13,7 @@ use Psalm\Tests\TestCase; use Psalm\Tests\TestConfig; -use function strpos; +use function str_contains; class NamespaceMoveTest extends TestCase { @@ -36,7 +36,7 @@ public function testValidCode( array $namespaces_to_move, ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/PropertyMoveTest.php b/tests/FileManipulation/PropertyMoveTest.php index 5b0afa6dd6d..9b6fd988d5f 100644 --- a/tests/FileManipulation/PropertyMoveTest.php +++ b/tests/FileManipulation/PropertyMoveTest.php @@ -13,7 +13,7 @@ use Psalm\Tests\TestCase; use Psalm\Tests\TestConfig; -use function strpos; +use function str_contains; class PropertyMoveTest extends TestCase { @@ -36,7 +36,7 @@ public function testValidCode( array $properties_to_move, ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileReferenceTest.php b/tests/FileReferenceTest.php index 770e96a2ec9..f71fee4033d 100644 --- a/tests/FileReferenceTest.php +++ b/tests/FileReferenceTest.php @@ -13,7 +13,7 @@ use UnexpectedValueException; use function count; -use function strpos; +use function str_contains; class FileReferenceTest extends TestCase { @@ -44,7 +44,7 @@ public function setUp(): void public function testReferenceLocations(string $input_code, string $symbol, array $expected_locations): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } @@ -90,7 +90,7 @@ public function testReferencedMethods( array $expected_file_references_to_missing_members, ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileUpdates/AnalyzedMethodTest.php b/tests/FileUpdates/AnalyzedMethodTest.php index 598efeb6189..fff514300b0 100644 --- a/tests/FileUpdates/AnalyzedMethodTest.php +++ b/tests/FileUpdates/AnalyzedMethodTest.php @@ -16,7 +16,7 @@ use function array_keys; use function getcwd; -use function strpos; +use function str_contains; use const DIRECTORY_SEPARATOR; @@ -60,7 +60,7 @@ public function testValidInclude( array $ignored_issues = [], ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileUpdates/CachedStorageTest.php b/tests/FileUpdates/CachedStorageTest.php index a41a33b86bb..836d8ac01f8 100644 --- a/tests/FileUpdates/CachedStorageTest.php +++ b/tests/FileUpdates/CachedStorageTest.php @@ -17,7 +17,7 @@ use function array_keys; use function getcwd; -use function strpos; +use function str_contains; use const DIRECTORY_SEPARATOR; @@ -50,7 +50,7 @@ public function setUp(): void public function testValidInclude(): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/IncludeTest.php b/tests/IncludeTest.php index 6aa37c925dd..cdc09d2db50 100644 --- a/tests/IncludeTest.php +++ b/tests/IncludeTest.php @@ -10,7 +10,7 @@ use function getcwd; use function preg_quote; -use function strpos; +use function str_contains; use const DIRECTORY_SEPARATOR; @@ -68,7 +68,7 @@ public function testInvalidInclude( string $error_message, array $directories = [], ): void { - if (strpos($this->getTestName(), 'SKIPPED-') !== false) { + if (str_contains($this->getTestName(), 'SKIPPED-')) { $this->markTestSkipped(); } diff --git a/tests/Internal/Codebase/InternalCallMapHandlerTest.php b/tests/Internal/Codebase/InternalCallMapHandlerTest.php index 4740a109690..a9db45dc6da 100644 --- a/tests/Internal/Codebase/InternalCallMapHandlerTest.php +++ b/tests/Internal/Codebase/InternalCallMapHandlerTest.php @@ -36,12 +36,15 @@ use function json_encode; use function preg_match; use function print_r; +use function str_contains; +use function str_ends_with; +use function str_starts_with; use function strcmp; -use function strncmp; use function strpos; use function substr; use function version_compare; +use const JSON_THROW_ON_ERROR; use const PHP_MAJOR_VERSION; use const PHP_MINOR_VERSION; use const PHP_VERSION; @@ -352,7 +355,7 @@ public function callMapEntryProvider(): iterable continue; } - yield "$function: " . (string) json_encode($entry) => [$function, $entry]; + yield "$function: " . (string) json_encode($entry, JSON_THROW_ON_ERROR) => [$function, $entry]; } } @@ -435,10 +438,7 @@ public function testIgnoredFunctionsStillFail(string $functionName, array $callM /** @var array $callMapEntry */ $this->assertEntryParameters($function, $callMapEntry); $this->assertEntryReturnType($function, $entryReturnType); - } catch (AssertionFailedError $e) { - $this->assertTrue(true); - return; - } catch (ExpectationFailedException $e) { + } catch (AssertionFailedError|ExpectationFailedException) { $this->assertTrue(true); return; } @@ -447,10 +447,7 @@ public function testIgnoredFunctionsStillFail(string $functionName, array $callM try { $this->assertEntryReturnType($function, $entryReturnType); - } catch (AssertionFailedError $e) { - $this->assertTrue(true); - return; - } catch (ExpectationFailedException $e) { + } catch (AssertionFailedError|ExpectationFailedException) { $this->assertTrue(true); return; } @@ -498,13 +495,13 @@ public function testCallMapCompliesWithReflection(string $functionName, array $c private function getReflectionFunction(string $functionName): ?ReflectionFunctionAbstract { try { - if (strpos($functionName, '::') !== false) { + if (str_contains($functionName, '::')) { return new ReflectionMethod($functionName); } /** @var callable-string $functionName */ return new ReflectionFunction($functionName); - } catch (ReflectionException $e) { + } catch (ReflectionException) { return null; } } @@ -532,12 +529,12 @@ private function assertEntryParameters(ReflectionFunctionAbstract $function, arr 'optional' => false, 'type' => $entry, ]; - if (strncmp($normalizedKey, '&', 1) === 0) { + if (str_starts_with($normalizedKey, '&')) { $normalizedEntry['byRef'] = true; $normalizedKey = substr($normalizedKey, 1); } - if (strncmp($normalizedKey, '...', 3) === 0) { + if (str_starts_with($normalizedKey, '...')) { $normalizedEntry['variadic'] = true; $normalizedKey = substr($normalizedKey, 3); } @@ -557,7 +554,7 @@ private function assertEntryParameters(ReflectionFunctionAbstract $function, arr } // Strip prefixes. - if (substr($normalizedKey, -1, 1) === "=") { + if (str_ends_with($normalizedKey, "=")) { $normalizedEntry['optional'] = true; $normalizedKey = substr($normalizedKey, 0, -1); } diff --git a/tests/Internal/Provider/ParserInstanceCacheProvider.php b/tests/Internal/Provider/ParserInstanceCacheProvider.php index c227fec9935..af3e7d44f9a 100644 --- a/tests/Internal/Provider/ParserInstanceCacheProvider.php +++ b/tests/Internal/Provider/ParserInstanceCacheProvider.php @@ -52,11 +52,7 @@ public function loadStatementsFromCache(string $file_path, int $file_modified_ti */ public function loadExistingStatementsFromCache(string $file_path): ?array { - if (isset($this->statements_cache[$file_path])) { - return $this->statements_cache[$file_path]; - } - - return null; + return $this->statements_cache[$file_path] ?? null; } /** @@ -71,11 +67,7 @@ public function saveStatementsToCache(string $file_path, string $file_content_ha public function loadExistingFileContentsFromCache(string $file_path): ?string { - if (isset($this->file_contents_cache[$file_path])) { - return $this->file_contents_cache[$file_path]; - } - - return null; + return $this->file_contents_cache[$file_path] ?? null; } public function cacheFileContents(string $file_path, string $file_contents): void diff --git a/tests/LanguageServer/DiagnosticTest.php b/tests/LanguageServer/DiagnosticTest.php index 29121fc6e88..f00c2cb060f 100644 --- a/tests/LanguageServer/DiagnosticTest.php +++ b/tests/LanguageServer/DiagnosticTest.php @@ -25,7 +25,8 @@ use Psalm\Tests\TestConfig; use function getcwd; -use function rand; +use function mt_getrandmax; +use function random_int; class DiagnosticTest extends AsyncTestCase { @@ -286,7 +287,7 @@ private function generateInitializeRequest(): array return [ 'method' => 'initialize', 'params' => [ - 'processId' => rand(), + 'processId' => random_int(0, mt_getrandmax()), 'locale' => 'en-us', 'capabilities' => [ 'workspace' => [ diff --git a/tests/LanguageServer/Message.php b/tests/LanguageServer/Message.php index 7ebbc6db03a..a7df3c14182 100644 --- a/tests/LanguageServer/Message.php +++ b/tests/LanguageServer/Message.php @@ -19,8 +19,6 @@ abstract class Message extends AdvancedJsonRpcMessage { /** * Returns the appropriate Message subclass - * - * @param array $msg */ public static function parseArray(array $msg): AdvancedJsonRpcMessage { diff --git a/tests/ProjectCheckerTest.php b/tests/ProjectCheckerTest.php index c2b07415b91..1057a0a2096 100644 --- a/tests/ProjectCheckerTest.php +++ b/tests/ProjectCheckerTest.php @@ -24,7 +24,6 @@ use function define; use function defined; -use function get_class; use function getcwd; use function microtime; use function ob_end_clean; @@ -142,7 +141,7 @@ public static function afterCodebasePopulated(AfterCodebasePopulatedEvent $event ), ); - $hook_class = get_class($hook); + $hook_class = $hook::class; $this->project_analyzer->getCodebase()->config->eventDispatcher->after_codebase_populated[] = $hook_class; diff --git a/tests/TaintTest.php b/tests/TaintTest.php index d685014c28b..3a48d4fe3b9 100644 --- a/tests/TaintTest.php +++ b/tests/TaintTest.php @@ -11,7 +11,7 @@ use function array_map; use function preg_quote; -use function strpos; +use function str_contains; use function trim; use const DIRECTORY_SEPARATOR; @@ -24,7 +24,7 @@ class TaintTest extends TestCase public function testValidCode(string $code): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } @@ -47,7 +47,7 @@ public function testValidCode(string $code): void */ public function testInvalidCode(string $code, string $error_message): void { - if (strpos($this->getTestName(), 'SKIPPED-') !== false) { + if (str_contains($this->getTestName(), 'SKIPPED-')) { $this->markTestSkipped(); } @@ -2587,7 +2587,7 @@ function evaluateExpression(DOMXPath $xpath) : mixed { */ public function multipleTaintIssuesAreDetected(string $code, array $expectedIssuesTypes): void { - if (strpos($this->getTestName(), 'SKIPPED-') !== false) { + if (str_contains($this->getTestName(), 'SKIPPED-')) { $this->markTestSkipped(); } diff --git a/tests/TestCase.php b/tests/TestCase.php index 8e61664f870..fe1e2c8ee0d 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -151,7 +151,7 @@ public static function assertArrayKeysAreStrings(array $array, string $message = public static function assertArrayKeysAreZeroOrString(array $array, string $message = ''): void { - $isZeroOrString = /** @param mixed $key */ fn($key): bool => $key === 0 || is_string($key); + $isZeroOrString = /** @param mixed $key */ fn(mixed $key): bool => $key === 0 || is_string($key); $validKeys = array_filter($array, $isZeroOrString, ARRAY_FILTER_USE_KEY); self::assertTrue(count($array) === count($validKeys), $message); } @@ -178,7 +178,7 @@ public static function assertStringIsParsableType(string $type, string $message try { $tokens = TypeTokenizer::tokenize($type); $union = TypeParser::parseTokens($tokens); - } catch (Throwable $_e) { + } catch (Throwable) { } self::assertInstanceOf(Union::class, $union, $message); } diff --git a/tests/Traits/InvalidCodeAnalysisTestTrait.php b/tests/Traits/InvalidCodeAnalysisTestTrait.php index e5a06f4e83c..6afcfc580fa 100644 --- a/tests/Traits/InvalidCodeAnalysisTestTrait.php +++ b/tests/Traits/InvalidCodeAnalysisTestTrait.php @@ -9,8 +9,8 @@ use Psalm\Exception\CodeException; use function preg_quote; +use function str_contains; use function str_replace; -use function strpos; use function strtoupper; use function substr; use function version_compare; @@ -54,16 +54,16 @@ public function testInvalidCode( string $php_version = '7.4', ): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'PHP80-') !== false) { + if (str_contains((string) $test_name, 'PHP80-')) { if (version_compare(PHP_VERSION, '8.0.0', '<')) { $this->markTestSkipped('Test case requires PHP 8.0.'); } - } elseif (strpos($test_name, 'SKIPPED-') !== false) { + } elseif (str_contains((string) $test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } // sanity check - do we have a PHP tag? - if (strpos($code, 'fail('Test case must have a getTestName(); - if (strpos($test_name, 'PHP80-') !== false) { + if (str_contains((string) $test_name, 'PHP80-')) { if (version_compare(PHP_VERSION, '8.0.0', '<')) { $this->markTestSkipped('Test case requires PHP 8.0.'); } - } elseif (strpos($test_name, 'PHP81-') !== false) { + } elseif (str_contains((string) $test_name, 'PHP81-')) { if (version_compare(PHP_VERSION, '8.1.0', '<')) { $this->markTestSkipped('Test case requires PHP 8.1.'); } - } elseif (strpos($test_name, 'SKIPPED-') !== false) { + } elseif (str_contains((string) $test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } // sanity check - do we have a PHP tag? - if (strpos($code, 'fail('Test case must have a getId(), ); - $this->assertContainsOnlyInstancesOf('Psalm\Type\Atomic', $reconciled->getAtomicTypes()); + $this->assertContainsOnlyInstancesOf(Atomic::class, $reconciled->getAtomicTypes()); } /** diff --git a/tests/UnusedCodeTest.php b/tests/UnusedCodeTest.php index 87e18726536..1b672bafc7b 100644 --- a/tests/UnusedCodeTest.php +++ b/tests/UnusedCodeTest.php @@ -16,7 +16,7 @@ use function getcwd; use function preg_quote; -use function strpos; +use function str_contains; use const DIRECTORY_SEPARATOR; @@ -49,7 +49,7 @@ public function setUp(): void public function testValidCode(string $code, array $ignored_issues = []): void { $test_name = $this->getTestName(); - if (strpos($test_name, 'SKIPPED-') !== false) { + if (str_contains($test_name, 'SKIPPED-')) { $this->markTestSkipped('Skipped due to a bug.'); } @@ -79,7 +79,7 @@ public function testValidCode(string $code, array $ignored_issues = []): void */ public function testInvalidCode(string $code, string $error_message, array $ignored_issues = []): void { - if (strpos($this->getTestName(), 'SKIPPED-') !== false) { + if (str_contains($this->getTestName(), 'SKIPPED-')) { $this->markTestSkipped(); } diff --git a/tests/fixtures/DummyProject/Bar.php b/tests/fixtures/DummyProject/Bar.php index 16245ebd252..6afdff30817 100644 --- a/tests/fixtures/DummyProject/Bar.php +++ b/tests/fixtures/DummyProject/Bar.php @@ -6,11 +6,10 @@ class Bar use SomeTrait; /** @var string */ - public $x; + public $x = 'hello'; public function __construct() { - $this->x = 'hello'; } } diff --git a/tests/fixtures/ModularConfig/Bar.php b/tests/fixtures/ModularConfig/Bar.php index 16245ebd252..6afdff30817 100644 --- a/tests/fixtures/ModularConfig/Bar.php +++ b/tests/fixtures/ModularConfig/Bar.php @@ -6,11 +6,10 @@ class Bar use SomeTrait; /** @var string */ - public $x; + public $x = 'hello'; public function __construct() { - $this->x = 'hello'; } } From 575db97c212cece45c6417c165f5c5c67492764e Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 14:00:20 +0200 Subject: [PATCH 02/63] Revert tests --- tests/AlgebraTest.php | 2 - tests/AnnotationTest.php | 2 - tests/ArgTest.php | 2 - tests/ArrayAccessTest.php | 2 - tests/ArrayAssignmentTest.php | 2 - tests/ArrayFunctionCallTest.php | 2 - tests/AssertAnnotationTest.php | 2 - tests/AssignmentTest.php | 2 - tests/AsyncTestCase.php | 6 +- tests/AttributeTest.php | 2 - tests/BadFormatTest.php | 2 - tests/BinaryOperationTest.php | 41 ++++++------ tests/ByIssueLevelAndTypeReportTest.php | 2 - tests/Cache/CacheTest.php | 2 +- tests/CallableTest.php | 2 - tests/CastTest.php | 2 - tests/CheckTypeTest.php | 2 - tests/ClassLikeDocblockParserTest.php | 2 - tests/ClassLikeStringTest.php | 2 - tests/ClassLoadOrderTest.php | 2 - tests/ClassScopeTest.php | 2 - tests/ClassTest.php | 2 - tests/ClosureTest.php | 2 - tests/CodebaseTest.php | 7 +- tests/CommentAnalyzerTest.php | 2 - tests/ComposerLockTest.php | 5 +- tests/Config/ConfigFileTest.php | 2 - tests/Config/ConfigTest.php | 7 +- tests/Config/CreatorTest.php | 2 - tests/Config/Plugin/AfterAnalysisPlugin.php | 2 - tests/Config/Plugin/FilePlugin.php | 2 - .../Plugin/FileTypeSelfRegisteringPlugin.php | 10 ++- tests/Config/Plugin/FunctionPlugin.php | 2 - tests/Config/Plugin/Hook/AfterAnalysis.php | 2 - .../CustomArrayMapFunctionStorageProvider.php | 8 +-- tests/Config/Plugin/Hook/FileProvider.php | 2 - .../Config/Plugin/Hook/FooMethodProvider.php | 2 - .../Plugin/Hook/FooPropertyProvider.php | 2 - .../Plugin/Hook/MagicFunctionProvider.php | 2 - tests/Config/Plugin/MethodPlugin.php | 2 - tests/Config/Plugin/PropertyPlugin.php | 2 - tests/Config/Plugin/StoragePlugin.php | 2 - tests/Config/PluginListTest.php | 11 ++-- tests/Config/PluginTest.php | 9 ++- tests/ConstValuesTest.php | 2 - tests/ConstantTest.php | 65 +++++++++---------- tests/CoreStubsTest.php | 2 - tests/DateTimeTest.php | 2 - tests/DeprecatedAnnotationTest.php | 2 - tests/DocCommentTest.php | 2 - tests/DocblockInheritanceTest.php | 2 - tests/DocumentationTest.php | 35 +++++----- tests/EndToEnd/DestructiveAutoloaderTest.php | 2 - tests/EndToEnd/PsalmEndToEndTest.php | 2 - tests/EndToEnd/PsalmRunnerTrait.php | 4 +- tests/EndToEnd/SuicidalAutoloaderTest.php | 2 - tests/EnumTest.php | 2 - tests/ErrorBaselineTest.php | 5 +- tests/ExpressionTest.php | 45 ++++++------- tests/ExtendsFinalClassTest.php | 2 - tests/ExtensionRequirementTest.php | 2 - tests/FileDiffTest.php | 21 +++--- .../ClassConstantMoveTest.php | 8 +-- tests/FileManipulation/ClassMoveTest.php | 8 +-- .../FileManipulationTestCase.php | 7 +- .../ImmutableAnnotationAdditionTest.php | 2 - tests/FileManipulation/MethodMoveTest.php | 8 +-- .../MissingPropertyTypeTest.php | 2 - .../MissingReturnTypeTest.php | 2 - tests/FileManipulation/NamespaceMoveTest.php | 8 +-- .../ParamNameMismatchTest.php | 2 - .../ParamTypeManipulationTest.php | 2 - tests/FileManipulation/PropertyMoveTest.php | 8 +-- .../PureAnnotationAdditionTest.php | 2 - .../RedundantCastManipulationTest.php | 2 - .../ReturnTypeManipulationTest.php | 2 - .../ThrowsBlockAdditionTest.php | 2 - .../UndefinedVariableManipulationTest.php | 2 - ...necessaryVarAnnotationManipulationTest.php | 2 - .../UnusedCodeManipulationTest.php | 2 - .../UnusedVariableManipulationTest.php | 2 - tests/FileReferenceTest.php | 10 ++- tests/FileUpdates/AnalyzedMethodTest.php | 8 +-- tests/FileUpdates/CachedStorageTest.php | 6 +- tests/FileUpdates/ErrorAfterUpdateTest.php | 4 +- tests/FileUpdates/ErrorFixTest.php | 4 +- tests/FileUpdates/TemporaryUpdateTest.php | 4 +- tests/ForbiddenCodeTest.php | 2 - tests/FunctionCallTest.php | 2 - tests/FunctionLikeDocblockParserTest.php | 2 - tests/GeneratorTest.php | 2 - tests/IfThisIsTest.php | 2 - tests/ImmutableAnnotationTest.php | 2 - tests/ImplementationRequirementTest.php | 2 - tests/IncludeTest.php | 10 ++- tests/IntRangeTest.php | 2 - tests/InterfaceTest.php | 2 - tests/Internal/CallMapTest.php | 2 - tests/Internal/CliUtilsTest.php | 2 - .../Codebase/InternalCallMapHandlerTest.php | 29 +++++---- .../ClassLikeStorageInstanceCacheProvider.php | 2 - .../FakeFileReferenceCacheProvider.php | 2 - .../Provider/FakeParserCacheProvider.php | 2 - .../FileStorageInstanceCacheProvider.php | 2 - .../Provider/ParserInstanceCacheProvider.php | 14 ++-- .../Provider/ProjectCacheProvider.php | 2 - tests/Internal/Scanner/FileScannerTest.php | 4 +- tests/InternalAnnotationTest.php | 2 - tests/IssueBufferTest.php | 2 - tests/IssueSuppressionTest.php | 2 - tests/JsonOutputTest.php | 4 +- tests/LanguageServer/CompletionTest.php | 2 - tests/LanguageServer/DiagnosticTest.php | 7 +- tests/LanguageServer/FileMapTest.php | 2 - tests/LanguageServer/Message.php | 4 +- tests/LanguageServer/PathMapperTest.php | 6 +- tests/LanguageServer/SymbolLookupTest.php | 4 +- tests/ListTest.php | 2 - tests/Loop/DoTest.php | 2 - tests/Loop/ForTest.php | 2 - tests/Loop/ForeachTest.php | 2 - tests/Loop/WhileTest.php | 2 - tests/MagicMethodAnnotationTest.php | 2 - tests/MagicPropertyTest.php | 2 - tests/MatchTest.php | 2 - tests/MethodCallTest.php | 2 - tests/MethodMutationTest.php | 2 - tests/MethodSignatureTest.php | 2 - tests/MixinAnnotationTest.php | 2 - tests/NamespaceTest.php | 2 - tests/NativeIntersectionsTest.php | 2 - tests/NativeUnionsTest.php | 2 - tests/Php40Test.php | 2 - tests/Php55Test.php | 2 - tests/Php56Test.php | 2 - tests/Php70Test.php | 2 - tests/Php71Test.php | 2 - tests/Progress/EchoProgress.php | 2 - tests/ProjectCheckerTest.php | 5 +- tests/PropertiesOfTest.php | 2 - tests/PropertyTypeInvarianceTest.php | 2 - tests/PropertyTypeTest.php | 2 - tests/PsalmPluginTest.php | 8 +-- tests/PureAnnotationTest.php | 2 - tests/PureCallableTest.php | 2 - tests/ReadonlyPropertyTest.php | 2 - tests/ReferenceConstraintTest.php | 2 - tests/ReferenceTest.php | 2 - tests/ReportOutputTest.php | 2 - tests/ReturnTypeProvider/ArrayColumnTest.php | 2 - tests/ReturnTypeProvider/ArraySliceTest.php | 2 - tests/ReturnTypeProvider/BasenameTest.php | 2 - tests/ReturnTypeProvider/DirnameTest.php | 2 - .../ReturnTypeProvider/ExceptionCodeTest.php | 2 - tests/ReturnTypeProvider/InArrayTest.php | 2 - .../MinMaxReturnTypeProviderTest.php | 2 - .../PowReturnTypeProviderTest.php | 2 - tests/ReturnTypeProvider/SprintfTest.php | 2 - tests/ReturnTypeTest.php | 2 - tests/StubTest.php | 2 - tests/SuperGlobalsTest.php | 2 - tests/SwitchTypeTest.php | 2 - tests/TaintTest.php | 10 ++- tests/Template/ClassStringMapTest.php | 2 - .../Template/ClassTemplateCovarianceTest.php | 2 - tests/Template/ClassTemplateExtendsTest.php | 2 - tests/Template/ClassTemplateTest.php | 2 - tests/Template/ConditionalReturnTypeTest.php | 2 - .../FunctionClassStringTemplateTest.php | 2 - tests/Template/FunctionTemplateAssertTest.php | 2 - tests/Template/FunctionTemplateTest.php | 2 - tests/Template/NestedTemplateTest.php | 2 - tests/Template/PropertiesOfTemplateTest.php | 2 - tests/Template/TraitTemplateTest.php | 2 - tests/TestCase.php | 6 +- tests/TestConfig.php | 7 +- tests/TestEnvironmentTest.php | 2 - tests/ThisOutTest.php | 2 - tests/ThrowsAnnotationTest.php | 2 - tests/ThrowsInGlobalScopeTest.php | 2 - tests/ToStringTest.php | 2 - tests/TraceTest.php | 2 - tests/TraitTest.php | 2 - tests/Traits/InvalidCodeAnalysisTestTrait.php | 12 ++-- tests/Traits/ValidCodeAnalysisTestTrait.php | 13 ++-- tests/TryCatchTest.php | 2 - tests/TypeAnnotationTest.php | 2 - tests/TypeCombinationTest.php | 2 - tests/TypeComparatorTest.php | 2 - tests/TypeParseTest.php | 2 - .../TypeReconciliation/ArrayKeyExistsTest.php | 2 - .../AssignmentInConditionalTest.php | 2 - tests/TypeReconciliation/ConditionalTest.php | 2 - tests/TypeReconciliation/EmptyTest.php | 2 - tests/TypeReconciliation/InArrayTest.php | 2 - tests/TypeReconciliation/IssetTest.php | 2 - tests/TypeReconciliation/ReconcilerTest.php | 6 +- .../RedundantConditionTest.php | 2 - tests/TypeReconciliation/ScopeTest.php | 2 - tests/TypeReconciliation/TypeAlgebraTest.php | 2 - tests/TypeReconciliation/TypeTest.php | 2 - tests/TypeReconciliation/ValueTest.php | 2 - tests/UnresolvableIncludeTest.php | 2 - tests/UnusedCodeTest.php | 8 +-- tests/UnusedVariableTest.php | 2 - tests/VariadicTest.php | 2 - tests/fixtures/DummyProject/Bar.php | 3 +- tests/fixtures/ModularConfig/Bar.php | 3 +- tests/somefile.php | 3 - 209 files changed, 231 insertions(+), 619 deletions(-) diff --git a/tests/AlgebraTest.php b/tests/AlgebraTest.php index 24d96e9e202..e3ec6254ac6 100644 --- a/tests/AlgebraTest.php +++ b/tests/AlgebraTest.php @@ -1,7 +1,5 @@ $key === 0 || is_string($key); + $isZeroOrString = /** @param mixed $key */ fn($key): bool => $key === 0 || is_string($key); $validKeys = array_filter($array, $isZeroOrString, ARRAY_FILTER_USE_KEY); self::assertTrue(count($array) === count($validKeys), $message); } @@ -190,7 +188,7 @@ public static function assertStringIsParsableType(string $type, string $message try { $tokens = TypeTokenizer::tokenize($type); $union = TypeParser::parseTokens($tokens); - } catch (Throwable) { + } catch (Throwable $_e) { } self::assertInstanceOf(Union::class, $union, $message); } diff --git a/tests/AttributeTest.php b/tests/AttributeTest.php index 1603c7d8436..18d82b04ec4 100644 --- a/tests/AttributeTest.php +++ b/tests/AttributeTest.php @@ -1,7 +1,5 @@ Decimal::class, - '$b' => Decimal::class, - '$c' => Decimal::class, - '$d' => Decimal::class, - '$f' => Decimal::class, - '$g' => Decimal::class, - '$h' => Decimal::class, - '$i' => Decimal::class, - '$j' => Decimal::class, - '$k' => Decimal::class, - '$l' => Decimal::class, - '$m' => Decimal::class, - '$n' => Decimal::class, - '$o' => Decimal::class, - '$p' => Decimal::class, - '$q' => Decimal::class, - '$r' => Decimal::class, - '$s' => Decimal::class, - '$t' => Decimal::class, + '$a' => 'Decimal\\Decimal', + '$b' => 'Decimal\\Decimal', + '$c' => 'Decimal\\Decimal', + '$d' => 'Decimal\\Decimal', + '$f' => 'Decimal\\Decimal', + '$g' => 'Decimal\\Decimal', + '$h' => 'Decimal\\Decimal', + '$i' => 'Decimal\\Decimal', + '$j' => 'Decimal\\Decimal', + '$k' => 'Decimal\\Decimal', + '$l' => 'Decimal\\Decimal', + '$m' => 'Decimal\\Decimal', + '$n' => 'Decimal\\Decimal', + '$o' => 'Decimal\\Decimal', + '$p' => 'Decimal\\Decimal', + '$q' => 'Decimal\\Decimal', + '$r' => 'Decimal\\Decimal', + '$s' => 'Decimal\\Decimal', + '$t' => 'Decimal\\Decimal', ]; $context = new Context(); diff --git a/tests/ByIssueLevelAndTypeReportTest.php b/tests/ByIssueLevelAndTypeReportTest.php index 930d0dad65e..2b8eb7a55f1 100644 --- a/tests/ByIssueLevelAndTypeReportTest.php +++ b/tests/ByIssueLevelAndTypeReportTest.php @@ -1,7 +1,5 @@ codebase->config, $this->codebase)) - ->registerHooksFromClass($hook::class); + ->registerHooksFromClass(get_class($hook)); $this->codebase->classlike_storage_provider->cache = new ClassLikeStorageInstanceCacheProvider; $this->analyzeFile('somefile.php', new Context); @@ -242,7 +241,7 @@ public static function beforeAddIssue(BeforeAddIssueEvent $event): ?bool }; (new PluginRegistrationSocket($this->codebase->config, $this->codebase)) - ->registerHooksFromClass($eventHandler::class); + ->registerHooksFromClass(get_class($eventHandler)); $this->analyzeFile('somefile.php', new Context); self::assertSame(0, IssueBuffer::getErrorCount()); diff --git a/tests/CommentAnalyzerTest.php b/tests/CommentAnalyzerTest.php index c663d27f5af..a3ddcc55d4c 100644 --- a/tests/CommentAnalyzerTest.php +++ b/tests/CommentAnalyzerTest.php @@ -1,7 +1,5 @@ getFileExtensions()); - self::assertSame($scannerMock::class, $config->getFiletypeScanners()[$extension] ?? null); - self::assertSame($analyzerMock::class, $config->getFiletypeAnalyzers()[$extension] ?? null); + self::assertSame(get_class($scannerMock), $config->getFiletypeScanners()[$extension] ?? null); + self::assertSame(get_class($analyzerMock), $config->getFiletypeAnalyzers()[$extension] ?? null); self::assertNull($expectedExceptionCode, 'Expected exception code was not thrown'); } diff --git a/tests/Config/CreatorTest.php b/tests/Config/CreatorTest.php index 2928e417c88..38015e8df35 100644 --- a/tests/Config/CreatorTest.php +++ b/tests/Config/CreatorTest.php @@ -1,7 +1,5 @@ diff --git a/tests/Config/Plugin/FunctionPlugin.php b/tests/Config/Plugin/FunctionPlugin.php index 53746b73ebb..b17575bda08 100644 --- a/tests/Config/Plugin/FunctionPlugin.php +++ b/tests/Config/Plugin/FunctionPlugin.php @@ -1,7 +1,5 @@ config; - (new PluginRegistrationSocket($config, $codebase))->registerHooksFromClass($hook::class); + (new PluginRegistrationSocket($config, $codebase))->registerHooksFromClass(get_class($hook)); $this->assertContains( - $hook::class, + get_class($hook), $this->project_analyzer->getCodebase()->config->eventDispatcher->after_codebase_populated, ); } @@ -887,7 +886,7 @@ public static function afterEveryFunctionCallAnalysis(AfterEveryFunctionCallAnal }; $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); - $this->project_analyzer->getCodebase()->config->eventDispatcher->after_every_function_checks[] = $plugin::class; + $this->project_analyzer->getCodebase()->config->eventDispatcher->after_every_function_checks[] = get_class($plugin); $file_path = (string) getcwd() . '/src/somefile.php'; diff --git a/tests/ConstValuesTest.php b/tests/ConstValuesTest.php index 564867fdabf..7ff3c51f7e1 100644 --- a/tests/ConstValuesTest.php +++ b/tests/ConstValuesTest.php @@ -1,7 +1,5 @@ [ - 'code' => <<<'PHP_WRAP' - 1]; - public const I = [9223372036854775807 => 1]; + 'code' => <<<'PHP' + 1]; + public const I = [9223372036854775807 => 1]; - // PHP_INT_MAX + 1 - public const SO = ['9223372036854775808' => 1]; -} -$s = A::S; -$i = A::I; -$so = A::SO; -PHP_WRAP -, + // PHP_INT_MAX + 1 + public const SO = ['9223372036854775808' => 1]; + } + $s = A::S; + $i = A::I; + $so = A::SO; + PHP, 'assertions' => [ '$s===' => 'array{9223372036854775807: 1}', '$i===' => 'array{9223372036854775807: 1}', @@ -1897,17 +1894,16 @@ class A { ], ], 'autoincrementAlmostOverflow' => [ - 'code' => <<<'PHP_WRAP' - 0, - 1, // expected key = PHP_INT_MAX - ]; -} -$s = A::I; -PHP_WRAP -, + 'code' => <<<'PHP' + 0, + 1, // expected key = PHP_INT_MAX + ]; + } + $s = A::I; + PHP, 'assertions' => [ '$s===' => 'array{9223372036854775806: 0, 9223372036854775807: 1}', ], @@ -2447,14 +2443,13 @@ class Foo { 'error_message' => 'InvalidStringClass', ], 'integerOverflowInArrayKey' => [ - 'code' => <<<'PHP_WRAP' - 1]; -} -PHP_WRAP -, + 'code' => <<<'PHP' + 1]; + } + PHP, 'error_message' => 'InvalidArrayOffset', ], 'autoincrementOverflow' => [ diff --git a/tests/CoreStubsTest.php b/tests/CoreStubsTest.php index 87f26f859fe..ed3d0b76327 100644 --- a/tests/CoreStubsTest.php +++ b/tests/CoreStubsTest.php @@ -1,7 +1,5 @@ getTestName(), 'SKIPPED-')) { + if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); } @@ -222,9 +218,9 @@ public function testInvalidCode(string $code, string $error_message, array $igno $this->project_analyzer->trackUnusedSuppressions(); } - $is_taint_test = str_contains($error_message, 'Tainted'); + $is_taint_test = strpos($error_message, 'Tainted') !== false; - $is_array_offset_test = strpos($error_message, 'ArrayOffset') && str_contains($error_message, 'PossiblyUndefined'); + $is_array_offset_test = strpos($error_message, 'ArrayOffset') && strpos($error_message, 'PossiblyUndefined') !== false; $this->project_analyzer->getConfig()->ensure_array_string_offsets_exist = $is_array_offset_test; $this->project_analyzer->getConfig()->ensure_array_int_offsets_exist = $is_array_offset_test; @@ -325,9 +321,9 @@ public function providerInvalidCodeParse(): array $blocks[0], $issue_name, $ignored_issues, - str_contains($issue_name, 'Unused') - || str_contains($issue_name, 'Unevaluated') - || str_contains($issue_name, 'Unnecessary'), + strpos($issue_name, 'Unused') !== false + || strpos($issue_name, 'Unevaluated') !== false + || strpos($issue_name, 'Unnecessary') !== false, $php_version, ]; } @@ -401,8 +397,11 @@ public function conciseExpected(Constraint $inner): Constraint { return new class ($inner) extends Constraint { - public function __construct(private readonly Constraint $inner) + private Constraint $inner; + + public function __construct(Constraint $inner) { + $this->inner = $inner; } public function toString(): string @@ -410,12 +409,18 @@ public function toString(): string return $this->inner->toString(); } - protected function matches(mixed $other): bool + /** + * @param mixed $other + */ + protected function matches($other): bool { return $this->inner->matches($other); } - protected function failureDescription(mixed $other): string + /** + * @param mixed $other + */ + protected function failureDescription($other): string { return $this->exporter()->shortenedExport($other) . ' ' . $this->toString(); } diff --git a/tests/EndToEnd/DestructiveAutoloaderTest.php b/tests/EndToEnd/DestructiveAutoloaderTest.php index 74a8a59e6de..400efeec9d6 100644 --- a/tests/EndToEnd/DestructiveAutoloaderTest.php +++ b/tests/EndToEnd/DestructiveAutoloaderTest.php @@ -1,7 +1,5 @@ [ - 'code' => <<<'PHP_WRAP' - 1]; -$i = [9223372036854775807 => 1]; + 'code' => <<<'PHP' + 1]; + $i = [9223372036854775807 => 1]; -// PHP_INT_MAX + 1 -$so = ['9223372036854775808' => 1]; -PHP_WRAP -, + // PHP_INT_MAX + 1 + $so = ['9223372036854775808' => 1]; + PHP, 'assertions' => [ '$s===' => 'array{9223372036854775807: 1}', '$i===' => 'array{9223372036854775807: 1}', @@ -43,14 +40,13 @@ public function providerValidCodeParse(): iterable ], ]; yield 'autoincrementAlmostOverflow' => [ - 'code' => <<<'PHP_WRAP' - 0, - 1, // expected key = PHP_INT_MAX -]; -PHP_WRAP -, + 'code' => <<<'PHP' + 0, + 1, // expected key = PHP_INT_MAX + ]; + PHP, 'assertions' => [ '$a===' => 'array{9223372036854775806: 0, 9223372036854775807: 1}', ], @@ -71,12 +67,11 @@ public function providerValidCodeParse(): iterable public function providerInvalidCodeParse(): iterable { yield 'integerOverflowInArrayKey' => [ - 'code' => <<<'PHP_WRAP' - 1]; -PHP_WRAP -, + 'code' => <<<'PHP' + 1]; + PHP, 'error_message' => 'InvalidArrayOffset', ]; diff --git a/tests/ExtendsFinalClassTest.php b/tests/ExtendsFinalClassTest.php index 229d7c51ac2..c2f18288763 100644 --- a/tests/ExtendsFinalClassTest.php +++ b/tests/ExtendsFinalClassTest.php @@ -1,7 +1,5 @@ getTestName(), 'SKIPPED-')) { + if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); } @@ -85,9 +84,9 @@ public function testPartialAstDiff( array $same_methods, array $same_signatures, array $changed_methods, - array $diff_map_offsets, + array $diff_map_offsets ): void { - if (str_contains($this->getTestName(), 'SKIPPED-')) { + if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); } @@ -154,12 +153,12 @@ private function assertTreesEqual(array $a, array $b): void $this->assertNotSame($a_stmt, $b_stmt); - $this->assertSame($a_stmt::class, $b_stmt::class); + $this->assertSame(get_class($a_stmt), get_class($b_stmt)); if ($a_stmt instanceof PhpParser\Node\Stmt\Expression && $b_stmt instanceof PhpParser\Node\Stmt\Expression ) { - $this->assertSame($a_stmt->expr::class, $b_stmt->expr::class); + $this->assertSame(get_class($a_stmt->expr), get_class($b_stmt->expr)); } if ($a_doc = $a_stmt->getDocComment()) { @@ -180,8 +179,8 @@ private function assertTreesEqual(array $a, array $b): void $a_stmt->getAttribute('endFilePos'), $b_stmt->getAttribute('endFilePos'), ($a_stmt instanceof PhpParser\Node\Stmt\Expression - ? $a_stmt->expr::class - : $a_stmt::class) + ? get_class($a_stmt->expr) + : get_class($a_stmt)) . ' on line ' . $a_stmt->getLine(), ); $this->assertSame($a_stmt->getLine(), $b_stmt->getLine()); diff --git a/tests/FileManipulation/ClassConstantMoveTest.php b/tests/FileManipulation/ClassConstantMoveTest.php index fd91a345030..f06239abb0a 100644 --- a/tests/FileManipulation/ClassConstantMoveTest.php +++ b/tests/FileManipulation/ClassConstantMoveTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/ClassMoveTest.php b/tests/FileManipulation/ClassMoveTest.php index 20185e5abe8..e49e0cf87f8 100644 --- a/tests/FileManipulation/ClassMoveTest.php +++ b/tests/FileManipulation/ClassMoveTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/FileManipulationTestCase.php b/tests/FileManipulation/FileManipulationTestCase.php index b681052cc86..de361f6ffd2 100644 --- a/tests/FileManipulation/FileManipulationTestCase.php +++ b/tests/FileManipulation/FileManipulationTestCase.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/ImmutableAnnotationAdditionTest.php b/tests/FileManipulation/ImmutableAnnotationAdditionTest.php index 0e3083911c4..926cef22aad 100644 --- a/tests/FileManipulation/ImmutableAnnotationAdditionTest.php +++ b/tests/FileManipulation/ImmutableAnnotationAdditionTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/MissingPropertyTypeTest.php b/tests/FileManipulation/MissingPropertyTypeTest.php index 9fe744661f5..afeb644ee88 100644 --- a/tests/FileManipulation/MissingPropertyTypeTest.php +++ b/tests/FileManipulation/MissingPropertyTypeTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/ParamNameMismatchTest.php b/tests/FileManipulation/ParamNameMismatchTest.php index 186885a4309..3dfd82d778a 100644 --- a/tests/FileManipulation/ParamNameMismatchTest.php +++ b/tests/FileManipulation/ParamNameMismatchTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileManipulation/PureAnnotationAdditionTest.php b/tests/FileManipulation/PureAnnotationAdditionTest.php index 2b44581a82e..3434481ad4f 100644 --- a/tests/FileManipulation/PureAnnotationAdditionTest.php +++ b/tests/FileManipulation/PureAnnotationAdditionTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } @@ -87,10 +85,10 @@ public function testReferencedMethods( array $expected_method_references_to_members, array $expected_method_references_to_missing_members, array $expected_file_references_to_members, - array $expected_file_references_to_missing_members, + array $expected_file_references_to_missing_members ): void { $test_name = $this->getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileUpdates/AnalyzedMethodTest.php b/tests/FileUpdates/AnalyzedMethodTest.php index fff514300b0..30e8f29fa12 100644 --- a/tests/FileUpdates/AnalyzedMethodTest.php +++ b/tests/FileUpdates/AnalyzedMethodTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileUpdates/CachedStorageTest.php b/tests/FileUpdates/CachedStorageTest.php index 836d8ac01f8..3e6b97bff90 100644 --- a/tests/FileUpdates/CachedStorageTest.php +++ b/tests/FileUpdates/CachedStorageTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } diff --git a/tests/FileUpdates/ErrorAfterUpdateTest.php b/tests/FileUpdates/ErrorAfterUpdateTest.php index 162c71c1f8e..670ee34f4b9 100644 --- a/tests/FileUpdates/ErrorAfterUpdateTest.php +++ b/tests/FileUpdates/ErrorAfterUpdateTest.php @@ -1,7 +1,5 @@ project_analyzer->getCodebase()->diff_methods = true; $this->project_analyzer->getCodebase()->reportUnusedCode(); diff --git a/tests/FileUpdates/ErrorFixTest.php b/tests/FileUpdates/ErrorFixTest.php index c6e9ffc0132..7ea00bafe0c 100644 --- a/tests/FileUpdates/ErrorFixTest.php +++ b/tests/FileUpdates/ErrorFixTest.php @@ -1,7 +1,5 @@ project_analyzer->getCodebase()->diff_methods = true; diff --git a/tests/FileUpdates/TemporaryUpdateTest.php b/tests/FileUpdates/TemporaryUpdateTest.php index 507b483f0c6..f8e1c0bf0ab 100644 --- a/tests/FileUpdates/TemporaryUpdateTest.php +++ b/tests/FileUpdates/TemporaryUpdateTest.php @@ -1,7 +1,5 @@ codebase; $codebase->diff_methods = true; diff --git a/tests/ForbiddenCodeTest.php b/tests/ForbiddenCodeTest.php index 0a1911b1665..86b36f5279e 100644 --- a/tests/ForbiddenCodeTest.php +++ b/tests/ForbiddenCodeTest.php @@ -1,7 +1,5 @@ project_analyzer->getCodebase(); @@ -66,9 +64,9 @@ public function testInvalidInclude( array $files, array $files_to_check, string $error_message, - array $directories = [], + array $directories = [] ): void { - if (str_contains($this->getTestName(), 'SKIPPED-')) { + if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); } diff --git a/tests/IntRangeTest.php b/tests/IntRangeTest.php index 852710db8f5..c7c09ae2d92 100644 --- a/tests/IntRangeTest.php +++ b/tests/IntRangeTest.php @@ -1,7 +1,5 @@ [$function, $entry]; + yield "$function: " . (string) json_encode($entry) => [$function, $entry]; } } @@ -438,7 +433,10 @@ public function testIgnoredFunctionsStillFail(string $functionName, array $callM /** @var array $callMapEntry */ $this->assertEntryParameters($function, $callMapEntry); $this->assertEntryReturnType($function, $entryReturnType); - } catch (AssertionFailedError|ExpectationFailedException) { + } catch (AssertionFailedError $e) { + $this->assertTrue(true); + return; + } catch (ExpectationFailedException $e) { $this->assertTrue(true); return; } @@ -447,7 +445,10 @@ public function testIgnoredFunctionsStillFail(string $functionName, array $callM try { $this->assertEntryReturnType($function, $entryReturnType); - } catch (AssertionFailedError|ExpectationFailedException) { + } catch (AssertionFailedError $e) { + $this->assertTrue(true); + return; + } catch (ExpectationFailedException $e) { $this->assertTrue(true); return; } @@ -495,13 +496,13 @@ public function testCallMapCompliesWithReflection(string $functionName, array $c private function getReflectionFunction(string $functionName): ?ReflectionFunctionAbstract { try { - if (str_contains($functionName, '::')) { + if (strpos($functionName, '::') !== false) { return new ReflectionMethod($functionName); } /** @var callable-string $functionName */ return new ReflectionFunction($functionName); - } catch (ReflectionException) { + } catch (ReflectionException $e) { return null; } } @@ -529,12 +530,12 @@ private function assertEntryParameters(ReflectionFunctionAbstract $function, arr 'optional' => false, 'type' => $entry, ]; - if (str_starts_with($normalizedKey, '&')) { + if (strncmp($normalizedKey, '&', 1) === 0) { $normalizedEntry['byRef'] = true; $normalizedKey = substr($normalizedKey, 1); } - if (str_starts_with($normalizedKey, '...')) { + if (strncmp($normalizedKey, '...', 3) === 0) { $normalizedEntry['variadic'] = true; $normalizedKey = substr($normalizedKey, 3); } @@ -554,7 +555,7 @@ private function assertEntryParameters(ReflectionFunctionAbstract $function, arr } // Strip prefixes. - if (str_ends_with($normalizedKey, "=")) { + if (substr($normalizedKey, -1, 1) === "=") { $normalizedEntry['optional'] = true; $normalizedKey = substr($normalizedKey, 0, -1); } diff --git a/tests/Internal/Provider/ClassLikeStorageInstanceCacheProvider.php b/tests/Internal/Provider/ClassLikeStorageInstanceCacheProvider.php index 096154de6e1..5af1cb945b1 100644 --- a/tests/Internal/Provider/ClassLikeStorageInstanceCacheProvider.php +++ b/tests/Internal/Provider/ClassLikeStorageInstanceCacheProvider.php @@ -1,7 +1,5 @@ statements_cache[$file_path] ?? null; + if (isset($this->statements_cache[$file_path])) { + return $this->statements_cache[$file_path]; + } + + return null; } /** @@ -67,7 +69,11 @@ public function saveStatementsToCache(string $file_path, string $file_content_ha public function loadExistingFileContentsFromCache(string $file_path): ?string { - return $this->file_contents_cache[$file_path] ?? null; + if (isset($this->file_contents_cache[$file_path])) { + return $this->file_contents_cache[$file_path]; + } + + return null; } public function cacheFileContents(string $file_path, string $file_contents): void diff --git a/tests/Internal/Provider/ProjectCacheProvider.php b/tests/Internal/Provider/ProjectCacheProvider.php index a8ad1219b4f..de162b842d8 100644 --- a/tests/Internal/Provider/ProjectCacheProvider.php +++ b/tests/Internal/Provider/ProjectCacheProvider.php @@ -1,7 +1,5 @@ addFile('somefile.php', $code); $this->analyzeFile('somefile.php', new Context()); diff --git a/tests/LanguageServer/CompletionTest.php b/tests/LanguageServer/CompletionTest.php index 7e6cb52bdae..942556f56cd 100644 --- a/tests/LanguageServer/CompletionTest.php +++ b/tests/LanguageServer/CompletionTest.php @@ -1,7 +1,5 @@ 'initialize', 'params' => [ - 'processId' => random_int(0, mt_getrandmax()), + 'processId' => rand(), 'locale' => 'en-us', 'capabilities' => [ 'workspace' => [ diff --git a/tests/LanguageServer/FileMapTest.php b/tests/LanguageServer/FileMapTest.php index b89aa90a23b..e17b19be5d1 100644 --- a/tests/LanguageServer/FileMapTest.php +++ b/tests/LanguageServer/FileMapTest.php @@ -1,7 +1,5 @@ configureClientRoot($client_root_provided_later); @@ -55,7 +53,7 @@ public function testMapsServerToClient( ?string $client_root_preconfigured, string $client_root_provided_later, string $client_path, - string $server_path, + string $server_path ): void { $mapper = new PathMapper($server_root, $client_root_preconfigured); $mapper->configureClientRoot($client_root_provided_later); diff --git a/tests/LanguageServer/SymbolLookupTest.php b/tests/LanguageServer/SymbolLookupTest.php index a0a36cb5dd2..d235bc33442 100644 --- a/tests/LanguageServer/SymbolLookupTest.php +++ b/tests/LanguageServer/SymbolLookupTest.php @@ -1,7 +1,5 @@ codebase->config; $config->throw_exception = false; diff --git a/tests/ListTest.php b/tests/ListTest.php index c36c4bac7df..5dce65e5491 100644 --- a/tests/ListTest.php +++ b/tests/ListTest.php @@ -1,7 +1,5 @@ project_analyzer->getCodebase()->config->eventDispatcher->after_codebase_populated[] = $hook_class; diff --git a/tests/PropertiesOfTest.php b/tests/PropertiesOfTest.php index 99a14e678d6..73562916830 100644 --- a/tests/PropertiesOfTest.php +++ b/tests/PropertiesOfTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } @@ -47,7 +45,7 @@ public function testValidCode(string $code): void */ public function testInvalidCode(string $code, string $error_message): void { - if (str_contains($this->getTestName(), 'SKIPPED-')) { + if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); } @@ -2587,7 +2585,7 @@ function evaluateExpression(DOMXPath $xpath) : mixed { */ public function multipleTaintIssuesAreDetected(string $code, array $expectedIssuesTypes): void { - if (str_contains($this->getTestName(), 'SKIPPED-')) { + if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); } diff --git a/tests/Template/ClassStringMapTest.php b/tests/Template/ClassStringMapTest.php index 78ed8b7f354..c5105462d18 100644 --- a/tests/Template/ClassStringMapTest.php +++ b/tests/Template/ClassStringMapTest.php @@ -1,7 +1,5 @@ $key === 0 || is_string($key); + $isZeroOrString = /** @param mixed $key */ fn($key): bool => $key === 0 || is_string($key); $validKeys = array_filter($array, $isZeroOrString, ARRAY_FILTER_USE_KEY); self::assertTrue(count($array) === count($validKeys), $message); } @@ -178,7 +176,7 @@ public static function assertStringIsParsableType(string $type, string $message try { $tokens = TypeTokenizer::tokenize($type); $union = TypeParser::parseTokens($tokens); - } catch (Throwable) { + } catch (Throwable $_e) { } self::assertInstanceOf(Union::class, $union, $message); } diff --git a/tests/TestConfig.php b/tests/TestConfig.php index 572deabbce6..abb93284499 100644 --- a/tests/TestConfig.php +++ b/tests/TestConfig.php @@ -1,7 +1,5 @@ '; } - public function getComposerFilePathForClassLike(string $fq_classlike_name): string|false + /** + * @return false + */ + public function getComposerFilePathForClassLike(string $fq_classlike_name): bool { return false; } diff --git a/tests/TestEnvironmentTest.php b/tests/TestEnvironmentTest.php index 7b6a1b587b1..5a123791289 100644 --- a/tests/TestEnvironmentTest.php +++ b/tests/TestEnvironmentTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains((string) $test_name, 'PHP80-')) { + if (strpos($test_name, 'PHP80-') !== false) { if (version_compare(PHP_VERSION, '8.0.0', '<')) { $this->markTestSkipped('Test case requires PHP 8.0.'); } - } elseif (str_contains((string) $test_name, 'SKIPPED-')) { + } elseif (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } // sanity check - do we have a PHP tag? - if (!str_contains($code, 'fail('Test case must have a getTestName(); - if (str_contains((string) $test_name, 'PHP80-')) { + if (strpos($test_name, 'PHP80-') !== false) { if (version_compare(PHP_VERSION, '8.0.0', '<')) { $this->markTestSkipped('Test case requires PHP 8.0.'); } - } elseif (str_contains((string) $test_name, 'PHP81-')) { + } elseif (strpos($test_name, 'PHP81-') !== false) { if (version_compare(PHP_VERSION, '8.1.0', '<')) { $this->markTestSkipped('Test case requires PHP 8.1.'); } - } elseif (str_contains((string) $test_name, 'SKIPPED-')) { + } elseif (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } // sanity check - do we have a PHP tag? - if (!str_contains($code, 'fail('Test case must have a project_analyzer->getCodebase()->queueClassLikeForScanning(Countable::class); $this->project_analyzer->getCodebase()->scanFiles(); } @@ -87,7 +83,7 @@ public function testReconcilation(string $expected_type, Assertion $assertion, s $reconciled->getId(), ); - $this->assertContainsOnlyInstancesOf(Atomic::class, $reconciled->getAtomicTypes()); + $this->assertContainsOnlyInstancesOf('Psalm\Type\Atomic', $reconciled->getAtomicTypes()); } /** diff --git a/tests/TypeReconciliation/RedundantConditionTest.php b/tests/TypeReconciliation/RedundantConditionTest.php index b6e01460cc9..88142c7187e 100644 --- a/tests/TypeReconciliation/RedundantConditionTest.php +++ b/tests/TypeReconciliation/RedundantConditionTest.php @@ -1,7 +1,5 @@ getTestName(); - if (str_contains($test_name, 'SKIPPED-')) { + if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } @@ -79,7 +77,7 @@ public function testValidCode(string $code, array $ignored_issues = []): void */ public function testInvalidCode(string $code, string $error_message, array $ignored_issues = []): void { - if (str_contains($this->getTestName(), 'SKIPPED-')) { + if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); } diff --git a/tests/UnusedVariableTest.php b/tests/UnusedVariableTest.php index fb7583943b3..57f1a425d9c 100644 --- a/tests/UnusedVariableTest.php +++ b/tests/UnusedVariableTest.php @@ -1,7 +1,5 @@ x = 'hello'; } } diff --git a/tests/fixtures/ModularConfig/Bar.php b/tests/fixtures/ModularConfig/Bar.php index 6afdff30817..16245ebd252 100644 --- a/tests/fixtures/ModularConfig/Bar.php +++ b/tests/fixtures/ModularConfig/Bar.php @@ -6,10 +6,11 @@ class Bar use SomeTrait; /** @var string */ - public $x = 'hello'; + public $x; public function __construct() { + $this->x = 'hello'; } } diff --git a/tests/somefile.php b/tests/somefile.php index 783c5db66cd..1ce2c088a7f 100644 --- a/tests/somefile.php +++ b/tests/somefile.php @@ -1,5 +1,2 @@ Date: Thu, 19 Oct 2023 14:16:08 +0200 Subject: [PATCH 03/63] Fixes --- .../Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php | 2 +- src/Psalm/Internal/Codebase/Populator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php index af3618d3024..e5e45241fea 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php @@ -71,7 +71,7 @@ public static function analyze( $elseif_context = $if_conditional_scope->if_context; $cond_referenced_var_ids = $if_conditional_scope->cond_referenced_var_ids; $assigned_in_conditional_var_ids = $if_conditional_scope->assigned_in_conditional_var_ids; - } catch (ScopeAnalysisException $e) { + } catch (ScopeAnalysisException) { return false; } diff --git a/src/Psalm/Internal/Codebase/Populator.php b/src/Psalm/Internal/Codebase/Populator.php index dc5c9ac7dc4..338d2278e74 100644 --- a/src/Psalm/Internal/Codebase/Populator.php +++ b/src/Psalm/Internal/Codebase/Populator.php @@ -755,7 +755,7 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file foreach ($storage->referenced_classlikes as $fq_class_name) { try { $classlike_storage = $this->classlike_storage_provider->get($fq_class_name); - } catch (InvalidArgumentException $e) { + } catch (InvalidArgumentException) { continue; } From 19a5c01fbb5b90e610454e6b3b32241af410f0b2 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 14:16:41 +0200 Subject: [PATCH 04/63] Fix --- tests/AlgebraTest.php | 2 ++ tests/AnnotationTest.php | 2 ++ tests/ArgTest.php | 2 ++ tests/ArrayAccessTest.php | 2 ++ tests/ArrayAssignmentTest.php | 2 ++ tests/ArrayFunctionCallTest.php | 2 ++ tests/AssertAnnotationTest.php | 2 ++ tests/AssignmentTest.php | 2 ++ tests/AsyncTestCase.php | 2 ++ tests/AttributeTest.php | 2 ++ tests/BadFormatTest.php | 2 ++ tests/BinaryOperationTest.php | 2 ++ tests/ByIssueLevelAndTypeReportTest.php | 2 ++ tests/Cache/CacheTest.php | 2 +- tests/CallableTest.php | 2 ++ tests/CastTest.php | 2 ++ tests/CheckTypeTest.php | 2 ++ tests/ClassLikeDocblockParserTest.php | 2 ++ tests/ClassLikeStringTest.php | 2 ++ tests/ClassLoadOrderTest.php | 2 ++ tests/ClassScopeTest.php | 2 ++ tests/ClassTest.php | 2 ++ tests/ClosureTest.php | 2 ++ tests/CodebaseTest.php | 2 ++ tests/CommentAnalyzerTest.php | 2 ++ tests/ComposerLockTest.php | 5 +++-- tests/Config/ConfigFileTest.php | 2 ++ tests/Config/ConfigTest.php | 2 ++ tests/Config/CreatorTest.php | 2 ++ tests/Config/Plugin/AfterAnalysisPlugin.php | 2 ++ tests/Config/Plugin/FilePlugin.php | 2 ++ .../Config/Plugin/FileTypeSelfRegisteringPlugin.php | 2 ++ tests/Config/Plugin/FunctionPlugin.php | 2 ++ tests/Config/Plugin/Hook/AfterAnalysis.php | 2 ++ .../Hook/CustomArrayMapFunctionStorageProvider.php | 8 +++++--- tests/Config/Plugin/Hook/FileProvider.php | 2 ++ tests/Config/Plugin/Hook/FooMethodProvider.php | 2 ++ tests/Config/Plugin/Hook/FooPropertyProvider.php | 2 ++ tests/Config/Plugin/Hook/MagicFunctionProvider.php | 2 ++ tests/Config/Plugin/MethodPlugin.php | 2 ++ tests/Config/Plugin/PropertyPlugin.php | 2 ++ tests/Config/Plugin/StoragePlugin.php | 2 ++ tests/Config/PluginListTest.php | 11 +++++------ tests/Config/PluginTest.php | 2 ++ tests/ConstValuesTest.php | 2 ++ tests/ConstantTest.php | 2 ++ tests/CoreStubsTest.php | 2 ++ tests/DateTimeTest.php | 2 ++ tests/DeprecatedAnnotationTest.php | 2 ++ tests/DocCommentTest.php | 2 ++ tests/DocblockInheritanceTest.php | 2 ++ tests/DocumentationTest.php | 12 ++++-------- tests/EndToEnd/DestructiveAutoloaderTest.php | 2 ++ tests/EndToEnd/PsalmEndToEndTest.php | 2 ++ tests/EndToEnd/PsalmRunnerTrait.php | 4 +++- tests/EndToEnd/SuicidalAutoloaderTest.php | 2 ++ tests/EnumTest.php | 2 ++ tests/ErrorBaselineTest.php | 5 +++-- tests/ExpressionTest.php | 2 ++ tests/ExtendsFinalClassTest.php | 2 ++ tests/ExtensionRequirementTest.php | 2 ++ tests/FileDiffTest.php | 6 ++++-- tests/FileManipulation/ClassConstantMoveTest.php | 4 +++- tests/FileManipulation/ClassMoveTest.php | 4 +++- tests/FileManipulation/FileManipulationTestCase.php | 4 +++- .../ImmutableAnnotationAdditionTest.php | 2 ++ tests/FileManipulation/MethodMoveTest.php | 4 +++- tests/FileManipulation/MissingPropertyTypeTest.php | 2 ++ tests/FileManipulation/MissingReturnTypeTest.php | 2 ++ tests/FileManipulation/NamespaceMoveTest.php | 4 +++- tests/FileManipulation/ParamNameMismatchTest.php | 2 ++ tests/FileManipulation/ParamTypeManipulationTest.php | 2 ++ tests/FileManipulation/PropertyMoveTest.php | 4 +++- .../FileManipulation/PureAnnotationAdditionTest.php | 2 ++ .../RedundantCastManipulationTest.php | 2 ++ .../FileManipulation/ReturnTypeManipulationTest.php | 2 ++ tests/FileManipulation/ThrowsBlockAdditionTest.php | 2 ++ .../UndefinedVariableManipulationTest.php | 2 ++ .../UnnecessaryVarAnnotationManipulationTest.php | 2 ++ .../FileManipulation/UnusedCodeManipulationTest.php | 2 ++ .../UnusedVariableManipulationTest.php | 2 ++ tests/FileReferenceTest.php | 4 +++- tests/FileUpdates/AnalyzedMethodTest.php | 4 +++- tests/FileUpdates/CachedStorageTest.php | 2 ++ tests/FileUpdates/ErrorAfterUpdateTest.php | 4 +++- tests/FileUpdates/ErrorFixTest.php | 4 +++- tests/FileUpdates/TemporaryUpdateTest.php | 4 +++- tests/ForbiddenCodeTest.php | 2 ++ tests/FunctionCallTest.php | 2 ++ tests/FunctionLikeDocblockParserTest.php | 2 ++ tests/GeneratorTest.php | 2 ++ tests/IfThisIsTest.php | 2 ++ tests/ImmutableAnnotationTest.php | 2 ++ tests/ImplementationRequirementTest.php | 2 ++ tests/IncludeTest.php | 6 ++++-- tests/IntRangeTest.php | 2 ++ tests/InterfaceTest.php | 2 ++ tests/Internal/CallMapTest.php | 2 ++ tests/Internal/CliUtilsTest.php | 2 ++ .../Internal/Codebase/InternalCallMapHandlerTest.php | 2 ++ .../ClassLikeStorageInstanceCacheProvider.php | 2 ++ .../Provider/FakeFileReferenceCacheProvider.php | 2 ++ tests/Internal/Provider/FakeParserCacheProvider.php | 2 ++ .../Provider/FileStorageInstanceCacheProvider.php | 2 ++ .../Provider/ParserInstanceCacheProvider.php | 2 ++ tests/Internal/Provider/ProjectCacheProvider.php | 2 ++ tests/Internal/Scanner/FileScannerTest.php | 4 +++- tests/InternalAnnotationTest.php | 2 ++ tests/IssueBufferTest.php | 2 ++ tests/IssueSuppressionTest.php | 2 ++ tests/JsonOutputTest.php | 4 +++- tests/LanguageServer/CompletionTest.php | 2 ++ tests/LanguageServer/DiagnosticTest.php | 2 ++ tests/LanguageServer/FileMapTest.php | 2 ++ tests/LanguageServer/Message.php | 2 ++ tests/LanguageServer/PathMapperTest.php | 6 ++++-- tests/LanguageServer/SymbolLookupTest.php | 4 +++- tests/ListTest.php | 2 ++ tests/Loop/DoTest.php | 2 ++ tests/Loop/ForTest.php | 2 ++ tests/Loop/ForeachTest.php | 2 ++ tests/Loop/WhileTest.php | 2 ++ tests/MagicMethodAnnotationTest.php | 2 ++ tests/MagicPropertyTest.php | 2 ++ tests/MatchTest.php | 2 ++ tests/MethodCallTest.php | 2 ++ tests/MethodMutationTest.php | 2 ++ tests/MethodSignatureTest.php | 2 ++ tests/MixinAnnotationTest.php | 2 ++ tests/NamespaceTest.php | 2 ++ tests/NativeIntersectionsTest.php | 2 ++ tests/NativeUnionsTest.php | 2 ++ tests/Php40Test.php | 2 ++ tests/Php55Test.php | 2 ++ tests/Php56Test.php | 2 ++ tests/Php70Test.php | 2 ++ tests/Php71Test.php | 2 ++ tests/Progress/EchoProgress.php | 2 ++ tests/ProjectCheckerTest.php | 2 ++ tests/PropertiesOfTest.php | 2 ++ tests/PropertyTypeInvarianceTest.php | 2 ++ tests/PropertyTypeTest.php | 2 ++ tests/PsalmPluginTest.php | 8 ++++---- tests/PureAnnotationTest.php | 2 ++ tests/PureCallableTest.php | 2 ++ tests/ReadonlyPropertyTest.php | 2 ++ tests/ReferenceConstraintTest.php | 2 ++ tests/ReferenceTest.php | 2 ++ tests/ReportOutputTest.php | 2 ++ tests/ReturnTypeProvider/ArrayColumnTest.php | 2 ++ tests/ReturnTypeProvider/ArraySliceTest.php | 2 ++ tests/ReturnTypeProvider/BasenameTest.php | 2 ++ tests/ReturnTypeProvider/DirnameTest.php | 2 ++ tests/ReturnTypeProvider/ExceptionCodeTest.php | 2 ++ tests/ReturnTypeProvider/InArrayTest.php | 2 ++ .../MinMaxReturnTypeProviderTest.php | 2 ++ .../ReturnTypeProvider/PowReturnTypeProviderTest.php | 2 ++ tests/ReturnTypeProvider/SprintfTest.php | 2 ++ tests/ReturnTypeTest.php | 2 ++ tests/StubTest.php | 2 ++ tests/SuperGlobalsTest.php | 2 ++ tests/SwitchTypeTest.php | 2 ++ tests/TaintTest.php | 2 ++ tests/Template/ClassStringMapTest.php | 2 ++ tests/Template/ClassTemplateCovarianceTest.php | 2 ++ tests/Template/ClassTemplateExtendsTest.php | 2 ++ tests/Template/ClassTemplateTest.php | 2 ++ tests/Template/ConditionalReturnTypeTest.php | 2 ++ tests/Template/FunctionClassStringTemplateTest.php | 2 ++ tests/Template/FunctionTemplateAssertTest.php | 2 ++ tests/Template/FunctionTemplateTest.php | 2 ++ tests/Template/NestedTemplateTest.php | 2 ++ tests/Template/PropertiesOfTemplateTest.php | 2 ++ tests/Template/TraitTemplateTest.php | 2 ++ tests/TestCase.php | 2 ++ tests/TestConfig.php | 2 ++ tests/TestEnvironmentTest.php | 2 ++ tests/ThisOutTest.php | 2 ++ tests/ThrowsAnnotationTest.php | 2 ++ tests/ThrowsInGlobalScopeTest.php | 2 ++ tests/ToStringTest.php | 2 ++ tests/TraceTest.php | 2 ++ tests/TraitTest.php | 2 ++ tests/Traits/InvalidCodeAnalysisTestTrait.php | 4 +++- tests/Traits/ValidCodeAnalysisTestTrait.php | 4 +++- tests/TryCatchTest.php | 2 ++ tests/TypeAnnotationTest.php | 2 ++ tests/TypeCombinationTest.php | 2 ++ tests/TypeComparatorTest.php | 2 ++ tests/TypeParseTest.php | 2 ++ tests/TypeReconciliation/ArrayKeyExistsTest.php | 2 ++ .../AssignmentInConditionalTest.php | 2 ++ tests/TypeReconciliation/ConditionalTest.php | 2 ++ tests/TypeReconciliation/EmptyTest.php | 2 ++ tests/TypeReconciliation/InArrayTest.php | 2 ++ tests/TypeReconciliation/IssetTest.php | 2 ++ tests/TypeReconciliation/ReconcilerTest.php | 2 ++ tests/TypeReconciliation/RedundantConditionTest.php | 2 ++ tests/TypeReconciliation/ScopeTest.php | 2 ++ tests/TypeReconciliation/TypeAlgebraTest.php | 2 ++ tests/TypeReconciliation/TypeTest.php | 2 ++ tests/TypeReconciliation/ValueTest.php | 2 ++ tests/UnresolvableIncludeTest.php | 2 ++ tests/UnusedCodeTest.php | 2 ++ tests/UnusedVariableTest.php | 2 ++ tests/VariadicTest.php | 2 ++ tests/somefile.php | 3 +++ 207 files changed, 449 insertions(+), 49 deletions(-) diff --git a/tests/AlgebraTest.php b/tests/AlgebraTest.php index e3ec6254ac6..24d96e9e202 100644 --- a/tests/AlgebraTest.php +++ b/tests/AlgebraTest.php @@ -1,5 +1,7 @@ inner->toString(); } - /** - * @param mixed $other - */ - protected function matches($other): bool + protected function matches(mixed $other): bool { return $this->inner->matches($other); } - /** - * @param mixed $other - */ - protected function failureDescription($other): string + protected function failureDescription(mixed $other): string { return $this->exporter()->shortenedExport($other) . ' ' . $this->toString(); } diff --git a/tests/EndToEnd/DestructiveAutoloaderTest.php b/tests/EndToEnd/DestructiveAutoloaderTest.php index 400efeec9d6..74a8a59e6de 100644 --- a/tests/EndToEnd/DestructiveAutoloaderTest.php +++ b/tests/EndToEnd/DestructiveAutoloaderTest.php @@ -1,5 +1,7 @@ getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); @@ -84,7 +86,7 @@ public function testPartialAstDiff( array $same_methods, array $same_signatures, array $changed_methods, - array $diff_map_offsets + array $diff_map_offsets, ): void { if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); diff --git a/tests/FileManipulation/ClassConstantMoveTest.php b/tests/FileManipulation/ClassConstantMoveTest.php index f06239abb0a..3e22aa14a0b 100644 --- a/tests/FileManipulation/ClassConstantMoveTest.php +++ b/tests/FileManipulation/ClassConstantMoveTest.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { diff --git a/tests/FileManipulation/ClassMoveTest.php b/tests/FileManipulation/ClassMoveTest.php index e49e0cf87f8..c2f5c8ee7a5 100644 --- a/tests/FileManipulation/ClassMoveTest.php +++ b/tests/FileManipulation/ClassMoveTest.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { diff --git a/tests/FileManipulation/FileManipulationTestCase.php b/tests/FileManipulation/FileManipulationTestCase.php index de361f6ffd2..06941283881 100644 --- a/tests/FileManipulation/FileManipulationTestCase.php +++ b/tests/FileManipulation/FileManipulationTestCase.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { diff --git a/tests/FileManipulation/ImmutableAnnotationAdditionTest.php b/tests/FileManipulation/ImmutableAnnotationAdditionTest.php index 926cef22aad..0e3083911c4 100644 --- a/tests/FileManipulation/ImmutableAnnotationAdditionTest.php +++ b/tests/FileManipulation/ImmutableAnnotationAdditionTest.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { diff --git a/tests/FileManipulation/MissingPropertyTypeTest.php b/tests/FileManipulation/MissingPropertyTypeTest.php index afeb644ee88..9fe744661f5 100644 --- a/tests/FileManipulation/MissingPropertyTypeTest.php +++ b/tests/FileManipulation/MissingPropertyTypeTest.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { diff --git a/tests/FileManipulation/ParamNameMismatchTest.php b/tests/FileManipulation/ParamNameMismatchTest.php index 3dfd82d778a..186885a4309 100644 --- a/tests/FileManipulation/ParamNameMismatchTest.php +++ b/tests/FileManipulation/ParamNameMismatchTest.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { diff --git a/tests/FileManipulation/PureAnnotationAdditionTest.php b/tests/FileManipulation/PureAnnotationAdditionTest.php index 3434481ad4f..2b44581a82e 100644 --- a/tests/FileManipulation/PureAnnotationAdditionTest.php +++ b/tests/FileManipulation/PureAnnotationAdditionTest.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { diff --git a/tests/FileUpdates/AnalyzedMethodTest.php b/tests/FileUpdates/AnalyzedMethodTest.php index 30e8f29fa12..598efeb6189 100644 --- a/tests/FileUpdates/AnalyzedMethodTest.php +++ b/tests/FileUpdates/AnalyzedMethodTest.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { diff --git a/tests/FileUpdates/CachedStorageTest.php b/tests/FileUpdates/CachedStorageTest.php index 3e6b97bff90..a41a33b86bb 100644 --- a/tests/FileUpdates/CachedStorageTest.php +++ b/tests/FileUpdates/CachedStorageTest.php @@ -1,5 +1,7 @@ project_analyzer->getCodebase()->diff_methods = true; $this->project_analyzer->getCodebase()->reportUnusedCode(); diff --git a/tests/FileUpdates/ErrorFixTest.php b/tests/FileUpdates/ErrorFixTest.php index 7ea00bafe0c..c6e9ffc0132 100644 --- a/tests/FileUpdates/ErrorFixTest.php +++ b/tests/FileUpdates/ErrorFixTest.php @@ -1,5 +1,7 @@ project_analyzer->getCodebase()->diff_methods = true; diff --git a/tests/FileUpdates/TemporaryUpdateTest.php b/tests/FileUpdates/TemporaryUpdateTest.php index f8e1c0bf0ab..507b483f0c6 100644 --- a/tests/FileUpdates/TemporaryUpdateTest.php +++ b/tests/FileUpdates/TemporaryUpdateTest.php @@ -1,5 +1,7 @@ codebase; $codebase->diff_methods = true; diff --git a/tests/ForbiddenCodeTest.php b/tests/ForbiddenCodeTest.php index 86b36f5279e..0a1911b1665 100644 --- a/tests/ForbiddenCodeTest.php +++ b/tests/ForbiddenCodeTest.php @@ -1,5 +1,7 @@ project_analyzer->getCodebase(); @@ -64,7 +66,7 @@ public function testInvalidInclude( array $files, array $files_to_check, string $error_message, - array $directories = [] + array $directories = [], ): void { if (strpos($this->getTestName(), 'SKIPPED-') !== false) { $this->markTestSkipped(); diff --git a/tests/IntRangeTest.php b/tests/IntRangeTest.php index c7c09ae2d92..852710db8f5 100644 --- a/tests/IntRangeTest.php +++ b/tests/IntRangeTest.php @@ -1,5 +1,7 @@ addFile('somefile.php', $code); $this->analyzeFile('somefile.php', new Context()); diff --git a/tests/LanguageServer/CompletionTest.php b/tests/LanguageServer/CompletionTest.php index 942556f56cd..7e6cb52bdae 100644 --- a/tests/LanguageServer/CompletionTest.php +++ b/tests/LanguageServer/CompletionTest.php @@ -1,5 +1,7 @@ configureClientRoot($client_root_provided_later); @@ -53,7 +55,7 @@ public function testMapsServerToClient( ?string $client_root_preconfigured, string $client_root_provided_later, string $client_path, - string $server_path + string $server_path, ): void { $mapper = new PathMapper($server_root, $client_root_preconfigured); $mapper->configureClientRoot($client_root_provided_later); diff --git a/tests/LanguageServer/SymbolLookupTest.php b/tests/LanguageServer/SymbolLookupTest.php index d235bc33442..a0a36cb5dd2 100644 --- a/tests/LanguageServer/SymbolLookupTest.php +++ b/tests/LanguageServer/SymbolLookupTest.php @@ -1,5 +1,7 @@ codebase->config; $config->throw_exception = false; diff --git a/tests/ListTest.php b/tests/ListTest.php index 5dce65e5491..c36c4bac7df 100644 --- a/tests/ListTest.php +++ b/tests/ListTest.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'PHP80-') !== false) { diff --git a/tests/Traits/ValidCodeAnalysisTestTrait.php b/tests/Traits/ValidCodeAnalysisTestTrait.php index b37acced357..e8b7ffce80e 100644 --- a/tests/Traits/ValidCodeAnalysisTestTrait.php +++ b/tests/Traits/ValidCodeAnalysisTestTrait.php @@ -1,5 +1,7 @@ getTestName(); if (strpos($test_name, 'PHP80-') !== false) { diff --git a/tests/TryCatchTest.php b/tests/TryCatchTest.php index c83e2b0911e..87a714e2359 100644 --- a/tests/TryCatchTest.php +++ b/tests/TryCatchTest.php @@ -1,5 +1,7 @@ Date: Thu, 19 Oct 2023 15:28:13 +0200 Subject: [PATCH 05/63] More finalization --- composer.json | 1 + examples/TemplateChecker.php | 4 +- examples/TemplateScanner.php | 2 +- examples/plugins/ClassUnqualifier.php | 2 +- examples/plugins/FunctionCasingChecker.php | 4 +- examples/plugins/InternalChecker.php | 2 +- .../plugins/PreventFloatAssignmentChecker.php | 4 +- examples/plugins/SafeArrayKeyChecker.php | 2 +- examples/plugins/StringChecker.php | 2 +- .../echo-checker/EchoChecker.php | 2 +- .../echo-checker/PluginEntryPoint.php | 2 +- phpunit.xml.dist | 2 +- src/Psalm/Config.php | 10 ++-- .../Exception/DocblockParseException.php | 2 +- src/Psalm/Internal/Analyzer/FileAnalyzer.php | 6 +-- .../Internal/Analyzer/NamespaceAnalyzer.php | 2 +- .../Internal/Analyzer/ProjectAnalyzer.php | 2 +- .../Statements/Expression/AssertionFinder.php | 48 +++++++++---------- .../Statements/Expression/CallAnalyzer.php | 2 +- .../Internal/Analyzer/StatementsAnalyzer.php | 4 +- src/Psalm/Internal/Codebase/Populator.php | 2 +- .../Internal/Codebase/VariableUseGraph.php | 2 +- src/Psalm/Internal/Diff/AstDiffer.php | 6 +-- .../BuildInfoCollector.php | 14 +++--- .../ExecutionEnvironment/GitInfoCollector.php | 8 ++-- .../LanguageServer/LanguageServer.php | 4 +- .../PhpVisitor/AssignmentMapVisitor.php | 2 +- .../PhpVisitor/CheckTrivialExprVisitor.php | 2 +- .../Reflector/ClassLikeDocblockParser.php | 2 +- .../PhpVisitor/ShortClosureVisitor.php | 2 +- .../PhpVisitor/SimpleNameResolver.php | 10 ++-- .../Internal/PluginManager/PluginList.php | 2 +- .../PluginManager/PluginListFactory.php | 2 +- .../ClassLikeStorageCacheProvider.php | 2 +- .../Provider/FileReferenceCacheProvider.php | 4 +- .../Provider/FileStorageCacheProvider.php | 6 +-- .../Internal/Provider/ParserCacheProvider.php | 6 +-- .../Provider/ProjectCacheProvider.php | 4 +- src/Psalm/Internal/Scanner/FileScanner.php | 2 +- .../Issue/InvalidInterfaceImplementation.php | 2 +- src/Psalm/Issue/PrivateFinalMethod.php | 2 +- src/Psalm/Issue/RiskyCast.php | 2 +- src/Psalm/Issue/UnusedBaselineEntry.php | 2 +- src/Psalm/IssueBuffer.php | 20 ++++---- src/Psalm/Progress/DefaultProgress.php | 2 +- src/Psalm/Report/CodeClimateReport.php | 4 +- src/Psalm/SourceControl/Git/CommitInfo.php | 14 +++--- src/Psalm/SourceControl/Git/RemoteInfo.php | 4 +- 48 files changed, 120 insertions(+), 119 deletions(-) diff --git a/composer.json b/composer.json index 12fa649812c..666260b66da 100644 --- a/composer.json +++ b/composer.json @@ -50,6 +50,7 @@ "amphp/phpunit-util": "^3", "bamarni/composer-bin-plugin": "^1.4", "brianium/paratest": "^6.9", + "dg/bypass-finals": "^1.5", "mockery/mockery": "^1.5", "nunomaduro/mock-final-classes": "^1.1", "php-parallel-lint/php-parallel-lint": "^1.2", diff --git a/examples/TemplateChecker.php b/examples/TemplateChecker.php index 7fec45544dc..4e911dd268d 100644 --- a/examples/TemplateChecker.php +++ b/examples/TemplateChecker.php @@ -30,7 +30,7 @@ use function strtolower; use function trim; -class TemplateAnalyzer extends Psalm\Internal\Analyzer\FileAnalyzer +final class TemplateAnalyzer extends Psalm\Internal\Analyzer\FileAnalyzer { final public const VIEW_CLASS = 'Your\\View\\Class'; @@ -148,7 +148,7 @@ private function checkMethod(MethodIdentifier $method_id, PhpParser\Node $stmt, /** * @param array $stmts */ - protected function checkWithViewClass(Context $context, array $stmts): void + private function checkWithViewClass(Context $context, array $stmts): void { $pseudo_method_stmts = []; diff --git a/examples/TemplateScanner.php b/examples/TemplateScanner.php index 681bf61bdc7..254b06dc338 100644 --- a/examples/TemplateScanner.php +++ b/examples/TemplateScanner.php @@ -14,7 +14,7 @@ use function preg_match; use function trim; -class TemplateScanner extends Psalm\Internal\Scanner\FileScanner +final class TemplateScanner extends Psalm\Internal\Scanner\FileScanner { final public const VIEW_CLASS = 'Your\\View\\Class'; diff --git a/examples/plugins/ClassUnqualifier.php b/examples/plugins/ClassUnqualifier.php index 97cecee648c..d2b05332329 100644 --- a/examples/plugins/ClassUnqualifier.php +++ b/examples/plugins/ClassUnqualifier.php @@ -12,7 +12,7 @@ use function strpos; use function strtolower; -class ClassUnqualifier implements AfterClassLikeExistenceCheckInterface +final class ClassUnqualifier implements AfterClassLikeExistenceCheckInterface { public static function afterClassLikeExistenceCheck( AfterClassLikeExistenceCheckEvent $event diff --git a/examples/plugins/FunctionCasingChecker.php b/examples/plugins/FunctionCasingChecker.php index f4d8c6a2e3e..56ec8983203 100644 --- a/examples/plugins/FunctionCasingChecker.php +++ b/examples/plugins/FunctionCasingChecker.php @@ -21,7 +21,7 @@ /** * Checks that functions and methods are correctly-cased */ -class FunctionCasingChecker implements AfterFunctionCallAnalysisInterface, AfterMethodCallAnalysisInterface +final class FunctionCasingChecker implements AfterFunctionCallAnalysisInterface, AfterMethodCallAnalysisInterface { public static function afterMethodCallAnalysis(AfterMethodCallAnalysisEvent $event): void { @@ -99,6 +99,6 @@ public static function afterFunctionCallAnalysis(AfterFunctionCallAnalysisEvent } } -class IncorrectFunctionCasing extends PluginIssue +final class IncorrectFunctionCasing extends PluginIssue { } diff --git a/examples/plugins/InternalChecker.php b/examples/plugins/InternalChecker.php index a5c6306bab0..0b2ea575187 100644 --- a/examples/plugins/InternalChecker.php +++ b/examples/plugins/InternalChecker.php @@ -12,7 +12,7 @@ use function strpos; -class InternalChecker implements AfterClassLikeAnalysisInterface +final class InternalChecker implements AfterClassLikeAnalysisInterface { /** @return null|false */ public static function afterStatementAnalysis(AfterClassLikeAnalysisEvent $event): ?bool diff --git a/examples/plugins/PreventFloatAssignmentChecker.php b/examples/plugins/PreventFloatAssignmentChecker.php index 18b5630efbc..5bc7b0765bb 100644 --- a/examples/plugins/PreventFloatAssignmentChecker.php +++ b/examples/plugins/PreventFloatAssignmentChecker.php @@ -12,7 +12,7 @@ /** * Prevents any assignment to a float value */ -class PreventFloatAssignmentChecker implements AfterExpressionAnalysisInterface +final class PreventFloatAssignmentChecker implements AfterExpressionAnalysisInterface { /** * Called after an expression has been checked @@ -40,6 +40,6 @@ public static function afterExpressionAnalysis(AfterExpressionAnalysisEvent $eve } } -class NoFloatAssignment extends PluginIssue +final class NoFloatAssignment extends PluginIssue { } diff --git a/examples/plugins/SafeArrayKeyChecker.php b/examples/plugins/SafeArrayKeyChecker.php index 5ea69772535..0360ed79155 100644 --- a/examples/plugins/SafeArrayKeyChecker.php +++ b/examples/plugins/SafeArrayKeyChecker.php @@ -7,7 +7,7 @@ use Psalm\Plugin\EventHandler\Event\AddRemoveTaintsEvent; use Psalm\Plugin\EventHandler\RemoveTaintsInterface; -class SafeArrayKeyChecker implements RemoveTaintsInterface +final class SafeArrayKeyChecker implements RemoveTaintsInterface { /** * Called to see what taints should be removed diff --git a/examples/plugins/StringChecker.php b/examples/plugins/StringChecker.php index 070bcde5ac4..1ce7a814086 100644 --- a/examples/plugins/StringChecker.php +++ b/examples/plugins/StringChecker.php @@ -16,7 +16,7 @@ use function strpos; use function strtolower; -class StringChecker implements AfterExpressionAnalysisInterface +final class StringChecker implements AfterExpressionAnalysisInterface { /** * Called after an expression has been checked diff --git a/examples/plugins/composer-based/echo-checker/EchoChecker.php b/examples/plugins/composer-based/echo-checker/EchoChecker.php index 668206c26e3..642e0a53e9c 100644 --- a/examples/plugins/composer-based/echo-checker/EchoChecker.php +++ b/examples/plugins/composer-based/echo-checker/EchoChecker.php @@ -11,7 +11,7 @@ use Psalm\Type\Atomic\TLiteralString; use Psalm\Type\Atomic\TString; -class EchoChecker implements AfterStatementAnalysisInterface +final class EchoChecker implements AfterStatementAnalysisInterface { /** * Called after a statement has been checked diff --git a/examples/plugins/composer-based/echo-checker/PluginEntryPoint.php b/examples/plugins/composer-based/echo-checker/PluginEntryPoint.php index 4d6102281e4..e83927e0d04 100644 --- a/examples/plugins/composer-based/echo-checker/PluginEntryPoint.php +++ b/examples/plugins/composer-based/echo-checker/PluginEntryPoint.php @@ -6,7 +6,7 @@ use Psalm\Plugin\RegistrationInterface; use SimpleXMLElement; -class PluginEntryPoint implements PluginEntryPointInterface +final class PluginEntryPoint implements PluginEntryPointInterface { public function __invoke(RegistrationInterface $registration, ?SimpleXMLElement $config = null): void { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 748be83439b..4f2c25cff79 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,7 @@ */ - protected array $universal_object_crates; + private array $universal_object_crates; /** * @var static|null @@ -223,7 +223,7 @@ class Config protected ?ProjectFileFilter $project_files = null; - protected ?ProjectFileFilter $extra_files = null; + private ?ProjectFileFilter $extra_files = null; /** * The base directory of this config file @@ -427,7 +427,7 @@ class Config private ?IncludeCollector $include_collector = null; - protected ?TaintAnalysisFileFilter $taint_analysis_ignored_files = null; + private ?TaintAnalysisFileFilter $taint_analysis_ignored_files = null; /** * @var bool whether to emit a backtrace of emitted issues to stderr @@ -567,7 +567,7 @@ class Config public array $config_warnings = []; /** @internal */ - protected function __construct() + private function __construct() { self::$instance = $this; $this->eventDispatcher = new EventDispatcher(); diff --git a/src/Psalm/Exception/DocblockParseException.php b/src/Psalm/Exception/DocblockParseException.php index 433f6632d2e..306c7eeb8dc 100644 --- a/src/Psalm/Exception/DocblockParseException.php +++ b/src/Psalm/Exception/DocblockParseException.php @@ -6,6 +6,6 @@ use Exception; -class DocblockParseException extends Exception +final class DocblockParseException extends Exception { } diff --git a/src/Psalm/Internal/Analyzer/FileAnalyzer.php b/src/Psalm/Internal/Analyzer/FileAnalyzer.php index 62aeac08f2f..85b2b57592f 100644 --- a/src/Psalm/Internal/Analyzer/FileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FileAnalyzer.php @@ -41,13 +41,13 @@ * @internal * @psalm-consistent-constructor */ -class FileAnalyzer extends SourceAnalyzer +final class FileAnalyzer extends SourceAnalyzer { use CanAlias; - protected ?string $root_file_path = null; + private ?string $root_file_path = null; - protected ?string $root_file_name = null; + private ?string $root_file_name = null; /** * @var array diff --git a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php index a6bac10d51a..7a9a50bdc25 100644 --- a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php @@ -35,7 +35,7 @@ final class NamespaceAnalyzer extends SourceAnalyzer * * @var array> */ - protected static array $public_namespace_constants = []; + private static array $public_namespace_constants = []; public function __construct( private readonly Namespace_ $namespace, /** diff --git a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index c4ff79c024f..ef9e130aad7 100644 --- a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -957,7 +957,7 @@ public function addExtraFile(string $file_path): void /** * @return list */ - protected function getDiffFiles(): array + private function getDiffFiles(): array { if (!$this->parser_cache_provider || !$this->project_cache_provider) { throw new UnexpectedValueException('Parser cache provider cannot be null here'); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php index 560305843d4..79e102de0e5 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php @@ -928,7 +928,7 @@ private static function processIrreconcilableFunctionCall( * @param PhpParser\Node\Expr\FuncCall|PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $expr * @return list>>> */ - protected static function processCustomAssertion( + private static function processCustomAssertion( PhpParser\Node\Expr $expr, ?string $this_class_name, FileSource $source, @@ -1230,7 +1230,7 @@ protected static function processCustomAssertion( /** * @return list */ - protected static function getInstanceOfAssertions( + private static function getInstanceOfAssertions( PhpParser\Node\Expr\Instanceof_ $stmt, ?string $this_class_name, FileSource $source, @@ -1295,7 +1295,7 @@ protected static function getInstanceOfAssertions( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional */ - protected static function hasNullVariable( + private static function hasNullVariable( PhpParser\Node\Expr\BinaryOp $conditional, FileSource $source, ): ?int { @@ -1366,7 +1366,7 @@ public static function hasTrueVariable( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional */ - protected static function hasEmptyArrayVariable( + private static function hasEmptyArrayVariable( PhpParser\Node\Expr\BinaryOp $conditional, ): ?int { if ($conditional->right instanceof PhpParser\Node\Expr\Array_ @@ -1387,7 +1387,7 @@ protected static function hasEmptyArrayVariable( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional */ - protected static function hasGetTypeCheck( + private static function hasGetTypeCheck( PhpParser\Node\Expr\BinaryOp $conditional, ): false|int { if ($conditional->right instanceof PhpParser\Node\Expr\FuncCall @@ -1414,7 +1414,7 @@ protected static function hasGetTypeCheck( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional */ - protected static function hasGetDebugTypeCheck( + private static function hasGetDebugTypeCheck( PhpParser\Node\Expr\BinaryOp $conditional, ): false|int { if ($conditional->right instanceof PhpParser\Node\Expr\FuncCall @@ -1443,7 +1443,7 @@ protected static function hasGetDebugTypeCheck( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional */ - protected static function hasGetClassCheck( + private static function hasGetClassCheck( PhpParser\Node\Expr\BinaryOp $conditional, FileSource $source, ): false|int { @@ -1535,7 +1535,7 @@ protected static function hasGetClassCheck( /** * @param Greater|GreaterOrEqual|Smaller|SmallerOrEqual $conditional */ - protected static function hasNonEmptyCountEqualityCheck( + private static function hasNonEmptyCountEqualityCheck( PhpParser\Node\Expr\BinaryOp $conditional, ?int &$min_count, ): false|int { @@ -1576,7 +1576,7 @@ protected static function hasNonEmptyCountEqualityCheck( /** * @param Greater|GreaterOrEqual|Smaller|SmallerOrEqual $conditional */ - protected static function hasLessThanCountEqualityCheck( + private static function hasLessThanCountEqualityCheck( PhpParser\Node\Expr\BinaryOp $conditional, ?int &$max_count, ): false|int { @@ -1624,7 +1624,7 @@ protected static function hasLessThanCountEqualityCheck( /** * @param Equal|Identical|NotEqual|NotIdentical $conditional */ - protected static function hasCountEqualityCheck( + private static function hasCountEqualityCheck( PhpParser\Node\Expr\BinaryOp $conditional, ?int &$count, ): false|int { @@ -1656,7 +1656,7 @@ protected static function hasCountEqualityCheck( /** * @param PhpParser\Node\Expr\BinaryOp\Greater|PhpParser\Node\Expr\BinaryOp\GreaterOrEqual $conditional */ - protected static function hasSuperiorNumberCheck( + private static function hasSuperiorNumberCheck( FileSource $source, PhpParser\Node\Expr\BinaryOp $conditional, ?int &$literal_value_comparison, @@ -1715,7 +1715,7 @@ protected static function hasSuperiorNumberCheck( /** * @param PhpParser\Node\Expr\BinaryOp\Smaller|PhpParser\Node\Expr\BinaryOp\SmallerOrEqual $conditional */ - protected static function hasInferiorNumberCheck( + private static function hasInferiorNumberCheck( FileSource $source, PhpParser\Node\Expr\BinaryOp $conditional, ?int &$literal_value_comparison, @@ -1774,7 +1774,7 @@ protected static function hasInferiorNumberCheck( /** * @param PhpParser\Node\Expr\BinaryOp\Greater|PhpParser\Node\Expr\BinaryOp\GreaterOrEqual $conditional */ - protected static function hasReconcilableNonEmptyCountEqualityCheck( + private static function hasReconcilableNonEmptyCountEqualityCheck( PhpParser\Node\Expr\BinaryOp $conditional, ): false|int { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall @@ -1795,7 +1795,7 @@ protected static function hasReconcilableNonEmptyCountEqualityCheck( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional */ - protected static function hasTypedValueComparison( + private static function hasTypedValueComparison( PhpParser\Node\Expr\BinaryOp $conditional, FileSource $source, ): false|int { @@ -1829,7 +1829,7 @@ protected static function hasTypedValueComparison( return false; } - protected static function hasIsACheck( + private static function hasIsACheck( PhpParser\Node\Expr\FuncCall $stmt, StatementsAnalyzer $source, ): bool { @@ -1925,7 +1925,7 @@ private static function handleIsTypeCheck( return $if_types; } - protected static function hasCallableCheck(PhpParser\Node\Expr\FuncCall $stmt): bool + private static function hasCallableCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'is_callable'; } @@ -1933,7 +1933,7 @@ protected static function hasCallableCheck(PhpParser\Node\Expr\FuncCall $stmt): /** * @return Reconciler::RECONCILIATION_* */ - protected static function hasClassExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): int + private static function hasClassExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): int { if ($stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'class_exists' @@ -1959,7 +1959,7 @@ protected static function hasClassExistsCheck(PhpParser\Node\Expr\FuncCall $stmt /** * @return 0|1|2 */ - protected static function hasTraitExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): int + private static function hasTraitExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): int { if ($stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'trait_exists' @@ -1982,22 +1982,22 @@ protected static function hasTraitExistsCheck(PhpParser\Node\Expr\FuncCall $stmt return 0; } - protected static function hasEnumExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool + private static function hasEnumExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'enum_exists'; } - protected static function hasInterfaceExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool + private static function hasInterfaceExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'interface_exists'; } - protected static function hasFunctionExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool + private static function hasFunctionExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'function_exists'; } - protected static function hasInArrayCheck(PhpParser\Node\Expr\FuncCall $stmt): bool + private static function hasInArrayCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { if ($stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'in_array' @@ -2015,13 +2015,13 @@ protected static function hasInArrayCheck(PhpParser\Node\Expr\FuncCall $stmt): b return false; } - protected static function hasNonEmptyCountCheck(PhpParser\Node\Expr\FuncCall $stmt): bool + private static function hasNonEmptyCountCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { return $stmt->name instanceof PhpParser\Node\Name && in_array(strtolower($stmt->name->getFirst()), ['count', 'sizeof']); } - protected static function hasArrayKeyExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool + private static function hasArrayKeyExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'array_key_exists'; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index 25b9f104cb3..f53816e5814 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -76,7 +76,7 @@ /** * @internal */ -class CallAnalyzer +abstract class CallAnalyzer { public static function collectSpecialInformation( FunctionLikeAnalyzer $source, diff --git a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php index be5d5e48762..8f4d2e4c9e6 100644 --- a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php @@ -96,9 +96,9 @@ */ final class StatementsAnalyzer extends SourceAnalyzer { - protected FileAnalyzer $file_analyzer; + private readonly FileAnalyzer $file_analyzer; - protected Codebase $codebase; + private readonly Codebase $codebase; /** * @var array diff --git a/src/Psalm/Internal/Codebase/Populator.php b/src/Psalm/Internal/Codebase/Populator.php index 338d2278e74..1a5c2935503 100644 --- a/src/Psalm/Internal/Codebase/Populator.php +++ b/src/Psalm/Internal/Codebase/Populator.php @@ -865,7 +865,7 @@ private function inheritConstantsFromTrait( } } - protected function inheritMethodsFromParent( + private function inheritMethodsFromParent( ClassLikeStorage $storage, ClassLikeStorage $parent_storage, ): void { diff --git a/src/Psalm/Internal/Codebase/VariableUseGraph.php b/src/Psalm/Internal/Codebase/VariableUseGraph.php index f17154c5a1f..615f7482ee9 100644 --- a/src/Psalm/Internal/Codebase/VariableUseGraph.php +++ b/src/Psalm/Internal/Codebase/VariableUseGraph.php @@ -17,7 +17,7 @@ final class VariableUseGraph extends DataFlowGraph { /** @var array> */ - protected array $backward_edges = []; + private array $backward_edges = []; /** @var array */ private array $nodes = []; diff --git a/src/Psalm/Internal/Diff/AstDiffer.php b/src/Psalm/Internal/Diff/AstDiffer.php index fcc2bd25edc..3c889711585 100644 --- a/src/Psalm/Internal/Diff/AstDiffer.php +++ b/src/Psalm/Internal/Diff/AstDiffer.php @@ -21,7 +21,7 @@ * * @internal */ -class AstDiffer +final class AstDiffer { /** * @param Closure(Stmt, Stmt, string, string, bool=): bool $is_equal @@ -29,7 +29,7 @@ class AstDiffer * @param array $b * @return array{0:non-empty-list>, 1: int, 2: int, 3: array} */ - protected static function calculateTrace( + private static function calculateTrace( Closure $is_equal, array $a, array $b, @@ -81,7 +81,7 @@ protected static function calculateTrace( * @return list * @psalm-pure */ - protected static function extractDiff(array $trace, int $x, int $y, array $a, array $b, array $bc): array + private static function extractDiff(array $trace, int $x, int $y, array $a, array $b, array $bc): array { $result = []; for ($d = count($trace) - 1; $d >= 0; --$d) { diff --git a/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php b/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php index aef34adfee4..0da2ea1dc62 100644 --- a/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php +++ b/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php @@ -28,7 +28,7 @@ final class BuildInfoCollector /** * Read environment variables. */ - protected array $readEnv = []; + private array $readEnv = []; public function __construct( /** @@ -70,7 +70,7 @@ public function collect(): array * @return $this * @psalm-suppress PossiblyUndefinedStringArrayOffset */ - protected function fillTravisCi(): self + private function fillTravisCi(): self { if (isset($this->env['TRAVIS']) && $this->env['TRAVIS'] && isset($this->env['TRAVIS_JOB_ID'])) { $this->readEnv['CI_JOB_ID'] = $this->env['TRAVIS_JOB_ID']; @@ -113,7 +113,7 @@ protected function fillTravisCi(): self * * @return $this */ - protected function fillCircleCi(): self + private function fillCircleCi(): self { if (isset($this->env['CIRCLECI']) && $this->env['CIRCLECI'] && isset($this->env['CIRCLE_BUILD_NUM'])) { $this->env['CI_BUILD_NUMBER'] = $this->env['CIRCLE_BUILD_NUM']; @@ -146,7 +146,7 @@ protected function fillCircleCi(): self * @psalm-suppress PossiblyUndefinedStringArrayOffset * @return $this */ - protected function fillAppVeyor(): self + private function fillAppVeyor(): self { if (isset($this->env['APPVEYOR']) && $this->env['APPVEYOR'] && isset($this->env['APPVEYOR_BUILD_NUMBER'])) { $this->readEnv['CI_BUILD_NUMBER'] = $this->env['APPVEYOR_BUILD_NUMBER']; @@ -193,7 +193,7 @@ protected function fillAppVeyor(): self * * @return $this */ - protected function fillJenkins(): self + private function fillJenkins(): self { if (isset($this->env['JENKINS_URL']) && isset($this->env['BUILD_NUMBER'])) { $this->readEnv['CI_BUILD_NUMBER'] = $this->env['BUILD_NUMBER']; @@ -217,7 +217,7 @@ protected function fillJenkins(): self * @psalm-suppress PossiblyUndefinedStringArrayOffset * @return $this */ - protected function fillScrutinizer(): self + private function fillScrutinizer(): self { if (isset($this->env['SCRUTINIZER']) && $this->env['SCRUTINIZER']) { $this->readEnv['CI_JOB_ID'] = $this->env['SCRUTINIZER_INSPECTION_UUID']; @@ -251,7 +251,7 @@ protected function fillScrutinizer(): self * @return $this * @psalm-suppress PossiblyUndefinedStringArrayOffset */ - protected function fillGithubActions(): BuildInfoCollector + private function fillGithubActions(): BuildInfoCollector { if (isset($this->env['GITHUB_ACTIONS'])) { $this->env['CI_NAME'] = 'github-actions'; diff --git a/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php b/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php index e23f5781a06..f659fef639d 100644 --- a/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php +++ b/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php @@ -29,7 +29,7 @@ final class GitInfoCollector /** * Git command. */ - protected SystemCommandExecutor $executor; + private readonly SystemCommandExecutor $executor; /** * Constructor. @@ -58,7 +58,7 @@ public function collect(): GitInfo * * @throws RuntimeException */ - protected function collectBranch(): string + private function collectBranch(): string { $branchesResult = $this->executor->execute('git branch'); @@ -78,7 +78,7 @@ protected function collectBranch(): string * * @throws RuntimeException */ - protected function collectCommit(): CommitInfo + private function collectCommit(): CommitInfo { $commitResult = $this->executor->execute('git log -1 --pretty=format:%H%n%aN%n%ae%n%cN%n%ce%n%s%n%at'); @@ -104,7 +104,7 @@ protected function collectCommit(): CommitInfo * @throws RuntimeException * @return list */ - protected function collectRemotes(): array + private function collectRemotes(): array { $remotesResult = $this->executor->execute('git remote -v'); diff --git a/src/Psalm/Internal/LanguageServer/LanguageServer.php b/src/Psalm/Internal/LanguageServer/LanguageServer.php index 30e8758c504..df2f691cd68 100644 --- a/src/Psalm/Internal/LanguageServer/LanguageServer.php +++ b/src/Psalm/Internal/LanguageServer/LanguageServer.php @@ -118,10 +118,10 @@ final class LanguageServer extends Dispatcher /** * The AMP Delay token */ - protected string $versionedAnalysisDelayToken = ''; + private string $versionedAnalysisDelayToken = ''; /** @var array}>> */ - protected array $issue_baseline = []; + private array $issue_baseline = []; /** * This should actually be a private property on `parent` diff --git a/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php b/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php index a1ea12f334e..de750effdf5 100644 --- a/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php @@ -20,7 +20,7 @@ final class AssignmentMapVisitor extends PhpParser\NodeVisitorAbstract /** * @var array> */ - protected array $assignment_map = []; + private array $assignment_map = []; public function __construct(protected ?string $this_class_name) { diff --git a/src/Psalm/Internal/PhpVisitor/CheckTrivialExprVisitor.php b/src/Psalm/Internal/PhpVisitor/CheckTrivialExprVisitor.php index 9c1bfa9de3f..1a3a14fdd2c 100644 --- a/src/Psalm/Internal/PhpVisitor/CheckTrivialExprVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/CheckTrivialExprVisitor.php @@ -14,7 +14,7 @@ final class CheckTrivialExprVisitor extends PhpParser\NodeVisitorAbstract /** * @var array */ - protected array $non_trivial_expr = []; + private array $non_trivial_expr = []; private function checkNonTrivialExpr(PhpParser\Node\Expr $node): bool { diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php index d073445d4e1..e94a64ba10f 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeDocblockParser.php @@ -528,7 +528,7 @@ public static function parse( * 'psalm-property-read'|'property-write'|'psalm-property-write' $property_tag * @throws DocblockParseException */ - protected static function addMagicPropertyToInfo( + private static function addMagicPropertyToInfo( Doc $comment, ClassLikeDocblockComment $info, array $specials, diff --git a/src/Psalm/Internal/PhpVisitor/ShortClosureVisitor.php b/src/Psalm/Internal/PhpVisitor/ShortClosureVisitor.php index 18137b22723..c10bc26ead5 100644 --- a/src/Psalm/Internal/PhpVisitor/ShortClosureVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ShortClosureVisitor.php @@ -16,7 +16,7 @@ final class ShortClosureVisitor extends PhpParser\NodeVisitorAbstract /** * @var array */ - protected array $used_variables = []; + private array $used_variables = []; public function enterNode(PhpParser\Node $node): ?int { diff --git a/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php b/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php index e62040ae3e9..455a22696df 100644 --- a/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php +++ b/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php @@ -202,7 +202,7 @@ private function resolveType(?Node $node): ?Node * @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_* * @return Name Resolved name, or original name with attribute */ - protected function resolveName(Name $name, int $type): Name + private function resolveName(Name $name, int $type): Name { $resolvedName = $this->nameContext->getResolvedName($name, $type); if (null !== $resolvedName) { @@ -220,12 +220,12 @@ protected function resolveName(Name $name, int $type): Name return $name; } - protected function resolveClassName(Name $name): Name + private function resolveClassName(Name $name): Name { return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL); } - protected function addNamespacedName(Stmt\Class_ $node): void + private function addNamespacedName(Stmt\Class_ $node): void { $node->setAttribute('namespacedName', Name::concat( $this->nameContext->getNamespace(), @@ -233,7 +233,7 @@ protected function addNamespacedName(Stmt\Class_ $node): void )); } - protected function resolveAttrGroups(Stmt\Class_ $node): void + private function resolveAttrGroups(Stmt\Class_ $node): void { foreach ($node->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { @@ -242,7 +242,7 @@ protected function resolveAttrGroups(Stmt\Class_ $node): void } } - protected function resolveTrait(Stmt\Trait_ $node): void + private function resolveTrait(Stmt\Trait_ $node): void { $resolvedName = Name::concat($this->nameContext->getNamespace(), (string) $node->name); diff --git a/src/Psalm/Internal/PluginManager/PluginList.php b/src/Psalm/Internal/PluginManager/PluginList.php index 89c41e7be3a..42ff53e13e6 100644 --- a/src/Psalm/Internal/PluginManager/PluginList.php +++ b/src/Psalm/Internal/PluginManager/PluginList.php @@ -16,7 +16,7 @@ /** * @internal */ -class PluginList +final class PluginList { /** @var ?array [pluginClass => packageName] */ private ?array $all_plugins = null; diff --git a/src/Psalm/Internal/PluginManager/PluginListFactory.php b/src/Psalm/Internal/PluginManager/PluginListFactory.php index c6daf1b634b..d64f4af373a 100644 --- a/src/Psalm/Internal/PluginManager/PluginListFactory.php +++ b/src/Psalm/Internal/PluginManager/PluginListFactory.php @@ -18,7 +18,7 @@ /** * @internal */ -class PluginListFactory +final class PluginListFactory { public function __construct(private readonly string $project_root, private readonly string $psalm_root) { diff --git a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php index c35c5e38238..2dfc5736357 100644 --- a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php @@ -26,7 +26,7 @@ /** * @internal */ -class ClassLikeStorageCacheProvider +final class ClassLikeStorageCacheProvider { private readonly Cache $cache; diff --git a/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php b/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php index 793e916989a..6a69e2018f3 100644 --- a/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php @@ -28,7 +28,7 @@ * @psalm-import-type FileMapType from Analyzer * @internal */ -class FileReferenceCacheProvider +final class FileReferenceCacheProvider { private const REFERENCE_CACHE_NAME = 'references'; private const CLASSLIKE_FILE_CACHE_NAME = 'classlike_files'; @@ -50,7 +50,7 @@ class FileReferenceCacheProvider private const FILE_MISSING_MEMBER_CACHE_NAME = 'file_missing_member'; private const UNKNOWN_MEMBER_CACHE_NAME = 'unknown_member_references'; private const METHOD_PARAM_USE_CACHE_NAME = 'method_param_uses'; - protected Cache $cache; + private readonly Cache $cache; public function __construct(protected Config $config) { diff --git a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php index 8419afd80fb..411d79ec9b4 100644 --- a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php @@ -25,7 +25,7 @@ /** * @internal */ -class FileStorageCacheProvider +final class FileStorageCacheProvider { private string $modified_timestamps = ''; @@ -73,7 +73,7 @@ public function writeToCache(FileStorage $storage, string $file_contents): void /** * @param lowercase-string $file_path */ - protected function storeInCache(string $file_path, FileStorage $storage): void + private function storeInCache(string $file_path, FileStorage $storage): void { $cache_location = $this->getCacheLocationForPath($file_path, true); $this->cache->saveItem($cache_location, $storage); @@ -119,7 +119,7 @@ private function getCacheHash(string $_unused_file_path, string $file_contents): /** * @param lowercase-string $file_path */ - protected function loadFromCache(string $file_path): ?FileStorage + private function loadFromCache(string $file_path): ?FileStorage { $storage = $this->cache->getItem($this->getCacheLocationForPath($file_path)); if ($storage instanceof FileStorage) { diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index 6c74fc06b22..36598b619d3 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -38,7 +38,7 @@ /** * @internal */ -class ParserCacheProvider +final class ParserCacheProvider { private const FILE_HASHES = 'file_hashes_json'; private const PARSER_CACHE_DIRECTORY = 'php-parser'; @@ -51,14 +51,14 @@ class ParserCacheProvider * * @var array|null */ - protected ?array $existing_file_content_hashes = null; + private ?array $existing_file_content_hashes = null; /** * A map of recently-added filename hashes to contents hashes * * @var array */ - protected array $new_file_content_hashes = []; + private array $new_file_content_hashes = []; public function __construct(Config $config, private readonly bool $use_file_cache = true) { diff --git a/src/Psalm/Internal/Provider/ProjectCacheProvider.php b/src/Psalm/Internal/Provider/ProjectCacheProvider.php index 125e6f9c725..26b02f25ca4 100644 --- a/src/Psalm/Internal/Provider/ProjectCacheProvider.php +++ b/src/Psalm/Internal/Provider/ProjectCacheProvider.php @@ -22,7 +22,7 @@ * * @internal */ -class ProjectCacheProvider +final class ProjectCacheProvider { private const GOOD_RUN_NAME = 'good_run'; private const COMPOSER_LOCK_HASH = 'composer_lock_hash'; @@ -116,7 +116,7 @@ public function updateComposerLockHash(): void file_put_contents($lock_hash_location, $this->composer_lock_hash); } - protected function getComposerLockHash(): string + private function getComposerLockHash(): string { if ($this->composer_lock_hash === null) { $cache_directory = Config::getInstance()->getCacheDirectory(); diff --git a/src/Psalm/Internal/Scanner/FileScanner.php b/src/Psalm/Internal/Scanner/FileScanner.php index d8ba100c47f..d7bf827fecb 100644 --- a/src/Psalm/Internal/Scanner/FileScanner.php +++ b/src/Psalm/Internal/Scanner/FileScanner.php @@ -18,7 +18,7 @@ * @internal * @psalm-consistent-constructor */ -class FileScanner implements FileSource +final class FileScanner implements FileSource { public function __construct(public string $file_path, public string $file_name, public bool $will_analyze) { diff --git a/src/Psalm/Issue/InvalidInterfaceImplementation.php b/src/Psalm/Issue/InvalidInterfaceImplementation.php index 1acfa745e1f..ddaa2a62c3d 100644 --- a/src/Psalm/Issue/InvalidInterfaceImplementation.php +++ b/src/Psalm/Issue/InvalidInterfaceImplementation.php @@ -4,7 +4,7 @@ namespace Psalm\Issue; -class InvalidInterfaceImplementation extends ClassIssue +final class InvalidInterfaceImplementation extends ClassIssue { final public const ERROR_LEVEL = -1; final public const SHORTCODE = 317; diff --git a/src/Psalm/Issue/PrivateFinalMethod.php b/src/Psalm/Issue/PrivateFinalMethod.php index 1df8c8421a0..889fbd4ef2a 100644 --- a/src/Psalm/Issue/PrivateFinalMethod.php +++ b/src/Psalm/Issue/PrivateFinalMethod.php @@ -4,7 +4,7 @@ namespace Psalm\Issue; -class PrivateFinalMethod extends MethodIssue +final class PrivateFinalMethod extends MethodIssue { final public const ERROR_LEVEL = 2; final public const SHORTCODE = 320; diff --git a/src/Psalm/Issue/RiskyCast.php b/src/Psalm/Issue/RiskyCast.php index 6f58ecdcf2e..f4cb5da41b5 100644 --- a/src/Psalm/Issue/RiskyCast.php +++ b/src/Psalm/Issue/RiskyCast.php @@ -4,7 +4,7 @@ namespace Psalm\Issue; -class RiskyCast extends CodeIssue +final class RiskyCast extends CodeIssue { final public const ERROR_LEVEL = 3; final public const SHORTCODE = 313; diff --git a/src/Psalm/Issue/UnusedBaselineEntry.php b/src/Psalm/Issue/UnusedBaselineEntry.php index 266ec1e8b4c..dd74a2239d1 100644 --- a/src/Psalm/Issue/UnusedBaselineEntry.php +++ b/src/Psalm/Issue/UnusedBaselineEntry.php @@ -4,7 +4,7 @@ namespace Psalm\Issue; -class UnusedBaselineEntry extends ClassIssue +final class UnusedBaselineEntry extends ClassIssue { final public const ERROR_LEVEL = -1; final public const SHORTCODE = 316; diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index 8008513c792..e2834f1eb37 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -86,39 +86,39 @@ final class IssueBuffer /** * @var array> */ - protected static array $issues_data = []; + private static array $issues_data = []; /** * @var array */ - protected static array $console_issues = []; + private static array $console_issues = []; /** * @var array */ - protected static array $fixable_issue_counts = []; + private static array $fixable_issue_counts = []; - protected static int $error_count = 0; + private static int $error_count = 0; /** * @var array */ - protected static array $emitted = []; + private static array $emitted = []; - protected static int $recording_level = 0; + private static int $recording_level = 0; /** @var array> */ - protected static array $recorded_issues = []; + private static array $recorded_issues = []; /** * @var array> */ - protected static array $unused_suppressions = []; + private static array $unused_suppressions = []; /** * @var array> */ - protected static array $used_suppressions = []; + private static array $used_suppressions = []; /** @var array */ private static array $server = []; @@ -887,7 +887,7 @@ public static function getOutput( return $output->create(); } - protected static function alreadyEmitted(string $message): bool + private static function alreadyEmitted(string $message): bool { $sham = sha1($message); diff --git a/src/Psalm/Progress/DefaultProgress.php b/src/Psalm/Progress/DefaultProgress.php index 57024cbf72f..59381fa938e 100644 --- a/src/Psalm/Progress/DefaultProgress.php +++ b/src/Psalm/Progress/DefaultProgress.php @@ -9,7 +9,7 @@ use function str_repeat; use function strlen; -class DefaultProgress extends LongProgress +final class DefaultProgress extends LongProgress { private const TOO_MANY_FILES = 1_500; diff --git a/src/Psalm/Report/CodeClimateReport.php b/src/Psalm/Report/CodeClimateReport.php index 9fd215026f0..61027d6371b 100644 --- a/src/Psalm/Report/CodeClimateReport.php +++ b/src/Psalm/Report/CodeClimateReport.php @@ -39,7 +39,7 @@ public function create(): string * convert our own severity to CodeClimate format * Values can be : info, minor, major, critical, or blocker */ - protected function convertSeverity(string $input): string + private function convertSeverity(string $input): string { if (Config::REPORT_INFO === $input) { return 'info'; @@ -58,7 +58,7 @@ protected function convertSeverity(string $input): string /** * calculate a unique fingerprint for a given issue */ - protected function calculateFingerprint(IssueData $issue): string + private function calculateFingerprint(IssueData $issue): string { return md5($issue->type.$issue->message.$issue->file_name.$issue->from.$issue->to); } diff --git a/src/Psalm/SourceControl/Git/CommitInfo.php b/src/Psalm/SourceControl/Git/CommitInfo.php index d10bbb41c0b..e0e70bad284 100644 --- a/src/Psalm/SourceControl/Git/CommitInfo.php +++ b/src/Psalm/SourceControl/Git/CommitInfo.php @@ -14,37 +14,37 @@ final class CommitInfo /** * Commit ID. */ - protected ?string $id = null; + private ?string $id = null; /** * Author name. */ - protected ?string $author_name = null; + private ?string $author_name = null; /** * Author email. */ - protected ?string $author_email = null; + private ?string $author_email = null; /** * Committer name. */ - protected ?string $committer_name = null; + private ?string $committer_name = null; /** * Committer email. */ - protected ?string $committer_email = null; + private ?string $committer_email = null; /** * Commit message. */ - protected ?string $message = null; + private ?string $message = null; /** * Commit message. */ - protected ?int $date = null; + private ?int $date = null; public function toArray(): array { diff --git a/src/Psalm/SourceControl/Git/RemoteInfo.php b/src/Psalm/SourceControl/Git/RemoteInfo.php index 91bf9a9b44a..ebb551b2186 100644 --- a/src/Psalm/SourceControl/Git/RemoteInfo.php +++ b/src/Psalm/SourceControl/Git/RemoteInfo.php @@ -14,12 +14,12 @@ final class RemoteInfo /** * Remote name. */ - protected ?string $name = null; + private ?string $name = null; /** * Remote URL. */ - protected ?string $url = null; + private ?string $url = null; public function toArray(): array { From 0b25592dbd62fbfd710842ceacf465e4a2eba7d2 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 17:13:49 +0200 Subject: [PATCH 06/63] Fix --- src/Psalm/FileBasedPluginAdapter.php | 7 +++++-- src/Psalm/Internal/Cache.php | 5 +++-- src/Psalm/Internal/Codebase/Analyzer.php | 8 ++++++-- .../Codebase/AssertionsFromInheritanceResolver.php | 5 +++-- .../Codebase/ClassConstantByWildcardResolver.php | 5 +++-- src/Psalm/Internal/Codebase/Functions.php | 6 ++++-- src/Psalm/Internal/Codebase/Populator.php | 9 +++++++-- src/Psalm/Internal/Codebase/Reflection.php | 6 ++++-- src/Psalm/Internal/Codebase/Scanner.php | 11 +++++++++-- .../FunctionDocblockManipulator.php | 7 +++++-- .../Client/Progress/LegacyProgress.php | 5 +++-- .../LanguageServer/Client/Progress/Progress.php | 6 ++++-- .../Internal/LanguageServer/Client/TextDocument.php | 6 ++++-- .../Internal/PhpVisitor/ConditionCloningVisitor.php | 5 +++-- .../Internal/PhpVisitor/NodeCleanerVisitor.php | 5 +++-- .../Internal/PhpVisitor/OffsetShifterVisitor.php | 7 +++++-- .../Internal/PhpVisitor/ParamReplacementVisitor.php | 6 ++++-- src/Psalm/Internal/PhpVisitor/TraitFinder.php | 5 +++-- .../Internal/PhpVisitor/TypeMappingVisitor.php | 6 ++++-- .../Internal/PhpVisitor/YieldTypeCollector.php | 5 +++-- .../PluginManager/Command/DisableCommand.php | 5 +++-- .../PluginManager/Command/EnableCommand.php | 5 +++-- .../Internal/PluginManager/Command/ShowCommand.php | 5 +++-- src/Psalm/Internal/PluginManager/ComposerLock.php | 5 +++-- src/Psalm/Internal/PluginManager/ConfigFile.php | 6 ++++-- src/Psalm/Internal/PluginManager/PluginList.php | 6 ++++-- .../Internal/PluginManager/PluginListFactory.php | 6 ++++-- .../Internal/Provider/FileReferenceProvider.php | 6 ++++-- src/Psalm/Internal/Provider/ParserCacheProvider.php | 6 ++++-- .../Internal/Provider/ProjectCacheProvider.php | 5 +++-- .../TypeVisitor/CanContainObjectTypeVisitor.php | 5 +++-- .../TypeVisitor/ContainsClassLikeVisitor.php | 5 +++-- .../Internal/TypeVisitor/FromDocblockSetter.php | 5 +++-- src/Psalm/Internal/TypeVisitor/TypeChecker.php | 12 ++++++++++-- src/Psalm/Internal/TypeVisitor/TypeLocalizer.php | 6 ++++-- src/Psalm/Internal/TypeVisitor/TypeScanner.php | 7 +++++-- src/Psalm/Plugin/ArgTypeInferer.php | 6 ++++-- src/Psalm/Plugin/DynamicTemplateProvider.php | 5 +++-- .../EventHandler/Event/AddRemoveTaintsEvent.php | 8 ++++++-- .../EventHandler/Event/AfterAnalysisEvent.php | 8 ++++++-- .../Event/AfterClassLikeAnalysisEvent.php | 9 +++++++-- .../Event/AfterClassLikeExistenceCheckEvent.php | 9 +++++++-- .../EventHandler/Event/AfterClassLikeVisitEvent.php | 9 +++++++-- .../Event/AfterCodebasePopulatedEvent.php | 5 +++-- .../Event/AfterEveryFunctionCallAnalysisEvent.php | 9 +++++++-- .../Event/AfterExpressionAnalysisEvent.php | 9 +++++++-- .../EventHandler/Event/AfterFileAnalysisEvent.php | 9 +++++++-- .../Event/AfterFunctionCallAnalysisEvent.php | 11 +++++++++-- .../Event/AfterFunctionLikeAnalysisEvent.php | 11 +++++++++-- .../Event/AfterMethodCallAnalysisEvent.php | 13 +++++++++++-- .../Event/AfterStatementAnalysisEvent.php | 9 +++++++-- .../EventHandler/Event/BeforeAddIssueEvent.php | 7 +++++-- .../Event/BeforeExpressionAnalysisEvent.php | 9 +++++++-- .../EventHandler/Event/BeforeFileAnalysisEvent.php | 8 ++++++-- .../Event/BeforeStatementAnalysisEvent.php | 9 +++++++-- .../Event/DynamicFunctionStorageProviderEvent.php | 11 +++++++++-- .../Event/FunctionExistenceProviderEvent.php | 6 ++++-- .../Event/FunctionParamsProviderEvent.php | 9 +++++++-- .../Event/FunctionReturnTypeProviderEvent.php | 9 +++++++-- .../Event/MethodExistenceProviderEvent.php | 8 ++++++-- .../Event/MethodParamsProviderEvent.php | 10 ++++++++-- .../Event/MethodReturnTypeProviderEvent.php | 13 +++++++++++-- .../Event/MethodVisibilityProviderEvent.php | 9 +++++++-- .../Event/PropertyExistenceProviderEvent.php | 10 ++++++++-- .../Event/PropertyTypeProviderEvent.php | 9 +++++++-- .../Event/PropertyVisibilityProviderEvent.php | 10 ++++++++-- .../EventHandler/Event/StringInterpreterEvent.php | 6 ++++-- src/Psalm/PluginFileExtensionsSocket.php | 5 +++-- src/Psalm/PluginRegistrationSocket.php | 6 ++++-- 69 files changed, 366 insertions(+), 138 deletions(-) diff --git a/src/Psalm/FileBasedPluginAdapter.php b/src/Psalm/FileBasedPluginAdapter.php index 0670e2ef1f8..e6aef73fcc8 100644 --- a/src/Psalm/FileBasedPluginAdapter.php +++ b/src/Psalm/FileBasedPluginAdapter.php @@ -24,8 +24,11 @@ final class FileBasedPluginAdapter implements PluginEntryPointInterface { private readonly string $path; - public function __construct(string $path, private readonly Config $config, private Codebase $codebase) - { + public function __construct( + string $path, + private readonly Config $config, + private Codebase $codebase, + ) { if (!$path) { throw new UnexpectedValueException('$path cannot be empty'); } diff --git a/src/Psalm/Internal/Cache.php b/src/Psalm/Internal/Cache.php index 8467f1d066d..86cf1ebf9bd 100644 --- a/src/Psalm/Internal/Cache.php +++ b/src/Psalm/Internal/Cache.php @@ -29,8 +29,9 @@ final class Cache { public bool $use_igbinary; - public function __construct(private readonly Config $config) - { + public function __construct( + private readonly Config $config, + ) { $this->use_igbinary = $config->use_igbinary; } diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php index 3a13427bf3b..eb217fe09d0 100644 --- a/src/Psalm/Internal/Codebase/Analyzer.php +++ b/src/Psalm/Internal/Codebase/Analyzer.php @@ -181,8 +181,12 @@ final class Analyzer */ public array $mutable_classes = []; - public function __construct(private readonly Config $config, private readonly FileProvider $file_provider, private readonly FileStorageProvider $file_storage_provider, private readonly Progress $progress) - { + public function __construct( + private readonly Config $config, + private readonly FileProvider $file_provider, + private readonly FileStorageProvider $file_storage_provider, + private readonly Progress $progress, + ) { } /** diff --git a/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php b/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php index 40b1cdb6688..57c577e022e 100644 --- a/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php +++ b/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php @@ -18,8 +18,9 @@ */ final class AssertionsFromInheritanceResolver { - public function __construct(private readonly Codebase $codebase) - { + public function __construct( + private readonly Codebase $codebase, + ) { } /** diff --git a/src/Psalm/Internal/Codebase/ClassConstantByWildcardResolver.php b/src/Psalm/Internal/Codebase/ClassConstantByWildcardResolver.php index e7253d2f78e..edfe9717c29 100644 --- a/src/Psalm/Internal/Codebase/ClassConstantByWildcardResolver.php +++ b/src/Psalm/Internal/Codebase/ClassConstantByWildcardResolver.php @@ -17,8 +17,9 @@ final class ClassConstantByWildcardResolver { private readonly StorageByPatternResolver $resolver; - public function __construct(private readonly Codebase $codebase) - { + public function __construct( + private readonly Codebase $codebase, + ) { $this->resolver = new StorageByPatternResolver(); } diff --git a/src/Psalm/Internal/Codebase/Functions.php b/src/Psalm/Internal/Codebase/Functions.php index 8178610016f..9bcbccdc5d0 100644 --- a/src/Psalm/Internal/Codebase/Functions.php +++ b/src/Psalm/Internal/Codebase/Functions.php @@ -54,8 +54,10 @@ final class Functions public DynamicFunctionStorageProvider $dynamic_storage_provider; - public function __construct(private readonly FileStorageProvider $file_storage_provider, private readonly Reflection $reflection) - { + public function __construct( + private readonly FileStorageProvider $file_storage_provider, + private readonly Reflection $reflection, + ) { $this->return_type_provider = new FunctionReturnTypeProvider(); $this->existence_provider = new FunctionExistenceProvider(); $this->params_provider = new FunctionParamsProvider(); diff --git a/src/Psalm/Internal/Codebase/Populator.php b/src/Psalm/Internal/Codebase/Populator.php index 1a5c2935503..15b790e9643 100644 --- a/src/Psalm/Internal/Codebase/Populator.php +++ b/src/Psalm/Internal/Codebase/Populator.php @@ -51,8 +51,13 @@ final class Populator */ private array $invalid_class_storages = []; - public function __construct(private ClassLikeStorageProvider $classlike_storage_provider, private readonly FileStorageProvider $file_storage_provider, private readonly ClassLikes $classlikes, private readonly FileReferenceProvider $file_reference_provider, private readonly Progress $progress) - { + public function __construct( + private ClassLikeStorageProvider $classlike_storage_provider, + private readonly FileStorageProvider $file_storage_provider, + private readonly ClassLikes $classlikes, + private readonly FileReferenceProvider $file_reference_provider, + private readonly Progress $progress, + ) { } public function populateCodebase(): void diff --git a/src/Psalm/Internal/Codebase/Reflection.php b/src/Psalm/Internal/Codebase/Reflection.php index c132d2bce57..9d8d50becb5 100644 --- a/src/Psalm/Internal/Codebase/Reflection.php +++ b/src/Psalm/Internal/Codebase/Reflection.php @@ -45,8 +45,10 @@ final class Reflection */ private static array $builtin_functions = []; - public function __construct(private readonly ClassLikeStorageProvider $storage_provider, private readonly Codebase $codebase) - { + public function __construct( + private readonly ClassLikeStorageProvider $storage_provider, + private readonly Codebase $codebase, + ) { self::$builtin_functions = []; } diff --git a/src/Psalm/Internal/Codebase/Scanner.php b/src/Psalm/Internal/Codebase/Scanner.php index 9359934e3d5..04ccb83895b 100644 --- a/src/Psalm/Internal/Codebase/Scanner.php +++ b/src/Psalm/Internal/Codebase/Scanner.php @@ -135,8 +135,15 @@ final class Scanner private bool $is_forked = false; - public function __construct(private readonly Codebase $codebase, private readonly Config $config, private readonly FileStorageProvider $file_storage_provider, private readonly FileProvider $file_provider, private readonly Reflection $reflection, private readonly FileReferenceProvider $file_reference_provider, private readonly Progress $progress) - { + public function __construct( + private readonly Codebase $codebase, + private readonly Config $config, + private readonly FileStorageProvider $file_storage_provider, + private readonly FileProvider $file_provider, + private readonly Reflection $reflection, + private readonly FileReferenceProvider $file_reference_provider, + private readonly Progress $progress, + ) { } /** diff --git a/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php b/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php index 9e00cc968de..fe63e1e38aa 100644 --- a/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php +++ b/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php @@ -107,8 +107,11 @@ public static function getForFunction( return $manipulator; } - private function __construct(string $file_path, private readonly Closure|Function_|ClassMethod|ArrowFunction $stmt, ProjectAnalyzer $project_analyzer) - { + private function __construct( + string $file_path, + private readonly Closure|Function_|ClassMethod|ArrowFunction $stmt, + ProjectAnalyzer $project_analyzer, + ) { $docblock = $stmt->getDocComment(); $this->docblock_start = $docblock ? $docblock->getStartFilePos() : (int)$stmt->getAttribute('startFilePos'); $this->docblock_end = $function_start = (int)$stmt->getAttribute('startFilePos'); diff --git a/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php b/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php index ab212c32e84..6350116a2b0 100644 --- a/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php +++ b/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php @@ -19,8 +19,9 @@ final class LegacyProgress implements ProgressInterface private string $status = self::STATUS_INACTIVE; private ?string $title = null; - public function __construct(private readonly ClientHandler $handler) - { + public function __construct( + private readonly ClientHandler $handler, + ) { } public function begin(string $title, ?string $message = null, ?int $percentage = null): void diff --git a/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php b/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php index 79d04a799fc..865dcd33e45 100644 --- a/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php +++ b/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php @@ -17,8 +17,10 @@ final class Progress implements ProgressInterface private string $status = self::STATUS_INACTIVE; private bool $withPercentage = false; - public function __construct(private readonly ClientHandler $handler, private readonly string $token) - { + public function __construct( + private readonly ClientHandler $handler, + private readonly string $token, + ) { } public function begin( diff --git a/src/Psalm/Internal/LanguageServer/Client/TextDocument.php b/src/Psalm/Internal/LanguageServer/Client/TextDocument.php index b186454b915..7d3e43f02db 100644 --- a/src/Psalm/Internal/LanguageServer/Client/TextDocument.php +++ b/src/Psalm/Internal/LanguageServer/Client/TextDocument.php @@ -15,8 +15,10 @@ */ final class TextDocument { - public function __construct(private readonly ClientHandler $handler, private readonly LanguageServer $server) - { + public function __construct( + private readonly ClientHandler $handler, + private readonly LanguageServer $server, + ) { } /** diff --git a/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php b/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php index 3e86158ad38..02c3ec4cb24 100644 --- a/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php @@ -14,8 +14,9 @@ */ final class ConditionCloningVisitor extends NodeVisitorAbstract { - public function __construct(private readonly NodeDataProvider $type_provider) - { + public function __construct( + private readonly NodeDataProvider $type_provider, + ) { } /** diff --git a/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php b/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php index 30fdc56e11f..936a58080a6 100644 --- a/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php @@ -12,8 +12,9 @@ */ final class NodeCleanerVisitor extends PhpParser\NodeVisitorAbstract { - public function __construct(private readonly NodeDataProvider $type_provider) - { + public function __construct( + private readonly NodeDataProvider $type_provider, + ) { } public function enterNode(PhpParser\Node $node): ?int diff --git a/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php b/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php index 02e5b977463..35313a96c0e 100644 --- a/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php @@ -16,8 +16,11 @@ final class OffsetShifterVisitor extends PhpParser\NodeVisitorAbstract /** * @param array $extra_offsets */ - public function __construct(private readonly int $file_offset, private readonly int $line_offset, private array $extra_offsets) - { + public function __construct( + private readonly int $file_offset, + private readonly int $line_offset, + private array $extra_offsets, + ) { } public function enterNode(PhpParser\Node $node): ?int diff --git a/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php b/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php index 97366cb3128..a10b264916f 100644 --- a/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php @@ -25,8 +25,10 @@ final class ParamReplacementVisitor extends PhpParser\NodeVisitorAbstract private bool $new_new_name_used = false; - public function __construct(private readonly string $old_name, private readonly string $new_name) - { + public function __construct( + private readonly string $old_name, + private readonly string $new_name, + ) { } public function enterNode(PhpParser\Node $node): ?int diff --git a/src/Psalm/Internal/PhpVisitor/TraitFinder.php b/src/Psalm/Internal/PhpVisitor/TraitFinder.php index ef0f2e3b600..9decb8d8af1 100644 --- a/src/Psalm/Internal/PhpVisitor/TraitFinder.php +++ b/src/Psalm/Internal/PhpVisitor/TraitFinder.php @@ -24,8 +24,9 @@ final class TraitFinder extends PhpParser\NodeVisitorAbstract /** @var list */ private array $matching_trait_nodes = []; - public function __construct(private readonly string $fq_trait_name) - { + public function __construct( + private readonly string $fq_trait_name, + ) { } public function enterNode(PhpParser\Node $node, bool &$traverseChildren = true): ?int diff --git a/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php b/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php index 9f5c45cbab9..5f9c6d7088c 100644 --- a/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php @@ -13,8 +13,10 @@ */ final class TypeMappingVisitor extends NodeVisitorAbstract { - public function __construct(private readonly NodeDataProvider $fake_type_provider, private readonly NodeDataProvider $real_type_provider) - { + public function __construct( + private readonly NodeDataProvider $fake_type_provider, + private readonly NodeDataProvider $real_type_provider, + ) { } /** diff --git a/src/Psalm/Internal/PhpVisitor/YieldTypeCollector.php b/src/Psalm/Internal/PhpVisitor/YieldTypeCollector.php index ed41640f4cb..94de49e6619 100644 --- a/src/Psalm/Internal/PhpVisitor/YieldTypeCollector.php +++ b/src/Psalm/Internal/PhpVisitor/YieldTypeCollector.php @@ -23,8 +23,9 @@ final class YieldTypeCollector extends NodeVisitorAbstract /** @var list */ private array $yield_types = []; - public function __construct(private readonly NodeDataProvider $nodes) - { + public function __construct( + private readonly NodeDataProvider $nodes, + ) { } public function enterNode(Node $node): ?int diff --git a/src/Psalm/Internal/PluginManager/Command/DisableCommand.php b/src/Psalm/Internal/PluginManager/Command/DisableCommand.php index aa174a85c62..a6cb1c505c8 100644 --- a/src/Psalm/Internal/PluginManager/Command/DisableCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/DisableCommand.php @@ -25,8 +25,9 @@ */ final class DisableCommand extends Command { - public function __construct(private readonly PluginListFactory $plugin_list_factory) - { + public function __construct( + private readonly PluginListFactory $plugin_list_factory, + ) { parent::__construct(); } diff --git a/src/Psalm/Internal/PluginManager/Command/EnableCommand.php b/src/Psalm/Internal/PluginManager/Command/EnableCommand.php index 858fe750852..71f520117f4 100644 --- a/src/Psalm/Internal/PluginManager/Command/EnableCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/EnableCommand.php @@ -25,8 +25,9 @@ */ final class EnableCommand extends Command { - public function __construct(private readonly PluginListFactory $plugin_list_factory) - { + public function __construct( + private readonly PluginListFactory $plugin_list_factory, + ) { parent::__construct(); } diff --git a/src/Psalm/Internal/PluginManager/Command/ShowCommand.php b/src/Psalm/Internal/PluginManager/Command/ShowCommand.php index fdc782562e4..e42b947f3aa 100644 --- a/src/Psalm/Internal/PluginManager/Command/ShowCommand.php +++ b/src/Psalm/Internal/PluginManager/Command/ShowCommand.php @@ -26,8 +26,9 @@ */ final class ShowCommand extends Command { - public function __construct(private readonly PluginListFactory $plugin_list_factory) - { + public function __construct( + private readonly PluginListFactory $plugin_list_factory, + ) { parent::__construct(); } diff --git a/src/Psalm/Internal/PluginManager/ComposerLock.php b/src/Psalm/Internal/PluginManager/ComposerLock.php index bb361a15f06..d806b09d81a 100644 --- a/src/Psalm/Internal/PluginManager/ComposerLock.php +++ b/src/Psalm/Internal/PluginManager/ComposerLock.php @@ -21,8 +21,9 @@ final class ComposerLock { /** @param string[] $file_names */ - public function __construct(private readonly array $file_names) - { + public function __construct( + private readonly array $file_names, + ) { } /** diff --git a/src/Psalm/Internal/PluginManager/ConfigFile.php b/src/Psalm/Internal/PluginManager/ConfigFile.php index 7ffb2f9084b..bb9883c2808 100644 --- a/src/Psalm/Internal/PluginManager/ConfigFile.php +++ b/src/Psalm/Internal/PluginManager/ConfigFile.php @@ -27,8 +27,10 @@ final class ConfigFile private ?int $psalm_tag_end_pos = null; - public function __construct(private readonly string $current_dir, ?string $explicit_path) - { + public function __construct( + private readonly string $current_dir, + ?string $explicit_path, + ) { if ($explicit_path) { $this->path = $explicit_path; } else { diff --git a/src/Psalm/Internal/PluginManager/PluginList.php b/src/Psalm/Internal/PluginManager/PluginList.php index 42ff53e13e6..b25536ffe27 100644 --- a/src/Psalm/Internal/PluginManager/PluginList.php +++ b/src/Psalm/Internal/PluginManager/PluginList.php @@ -24,8 +24,10 @@ final class PluginList /** @var ?array [pluginClass => ?packageName] */ private ?array $enabled_plugins = null; - public function __construct(private readonly ?ConfigFile $config_file, private readonly ComposerLock $composer_lock) - { + public function __construct( + private readonly ?ConfigFile $config_file, + private readonly ComposerLock $composer_lock, + ) { } /** diff --git a/src/Psalm/Internal/PluginManager/PluginListFactory.php b/src/Psalm/Internal/PluginManager/PluginListFactory.php index d64f4af373a..f3fab24774c 100644 --- a/src/Psalm/Internal/PluginManager/PluginListFactory.php +++ b/src/Psalm/Internal/PluginManager/PluginListFactory.php @@ -20,8 +20,10 @@ */ final class PluginListFactory { - public function __construct(private readonly string $project_root, private readonly string $psalm_root) - { + public function __construct( + private readonly string $project_root, + private readonly string $psalm_root, + ) { } public function __invoke(string $current_dir, ?string $config_file_path = null): PluginList diff --git a/src/Psalm/Internal/Provider/FileReferenceProvider.php b/src/Psalm/Internal/Provider/FileReferenceProvider.php index 22d39dc4876..77f161b61e5 100644 --- a/src/Psalm/Internal/Provider/FileReferenceProvider.php +++ b/src/Psalm/Internal/Provider/FileReferenceProvider.php @@ -165,8 +165,10 @@ final class FileReferenceProvider */ private static array $method_param_uses = []; - public function __construct(private readonly FileProvider $file_provider, public ?FileReferenceCacheProvider $cache = null) - { + public function __construct( + private readonly FileProvider $file_provider, + public ?FileReferenceCacheProvider $cache = null, + ) { } /** diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index 36598b619d3..d06376db8db 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -60,8 +60,10 @@ final class ParserCacheProvider */ private array $new_file_content_hashes = []; - public function __construct(Config $config, private readonly bool $use_file_cache = true) - { + public function __construct( + Config $config, + private readonly bool $use_file_cache = true, + ) { $this->cache = new Cache($config); } diff --git a/src/Psalm/Internal/Provider/ProjectCacheProvider.php b/src/Psalm/Internal/Provider/ProjectCacheProvider.php index 26b02f25ca4..91bf751fcc5 100644 --- a/src/Psalm/Internal/Provider/ProjectCacheProvider.php +++ b/src/Psalm/Internal/Provider/ProjectCacheProvider.php @@ -31,8 +31,9 @@ final class ProjectCacheProvider private ?string $composer_lock_hash = null; - public function __construct(private readonly string $composer_lock_location) - { + public function __construct( + private readonly string $composer_lock_location, + ) { } public function canDiffFiles(): bool diff --git a/src/Psalm/Internal/TypeVisitor/CanContainObjectTypeVisitor.php b/src/Psalm/Internal/TypeVisitor/CanContainObjectTypeVisitor.php index dca8271b55a..b1a1d8de366 100644 --- a/src/Psalm/Internal/TypeVisitor/CanContainObjectTypeVisitor.php +++ b/src/Psalm/Internal/TypeVisitor/CanContainObjectTypeVisitor.php @@ -16,8 +16,9 @@ final class CanContainObjectTypeVisitor extends TypeVisitor { private bool $contains_object_type = false; - public function __construct(private readonly Codebase $codebase) - { + public function __construct( + private readonly Codebase $codebase, + ) { } protected function enterNode(TypeNode $type): ?int diff --git a/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php b/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php index 6bad2c78a25..434b696a215 100644 --- a/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php +++ b/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php @@ -23,8 +23,9 @@ final class ContainsClassLikeVisitor extends TypeVisitor * @psalm-external-mutation-free * @param lowercase-string $fq_classlike_name */ - public function __construct(private readonly string $fq_classlike_name) - { + public function __construct( + private readonly string $fq_classlike_name, + ) { } /** diff --git a/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php b/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php index 22e290ac01e..a2a202c525d 100644 --- a/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php +++ b/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php @@ -16,8 +16,9 @@ */ final class FromDocblockSetter extends MutableTypeVisitor { - public function __construct(private readonly bool $from_docblock) - { + public function __construct( + private readonly bool $from_docblock, + ) { } /** * @return self::STOP_TRAVERSAL|self::DONT_TRAVERSE_CHILDREN|null diff --git a/src/Psalm/Internal/TypeVisitor/TypeChecker.php b/src/Psalm/Internal/TypeVisitor/TypeChecker.php index 34abe6bc798..fdc6dbc8a60 100644 --- a/src/Psalm/Internal/TypeVisitor/TypeChecker.php +++ b/src/Psalm/Internal/TypeVisitor/TypeChecker.php @@ -53,8 +53,16 @@ final class TypeChecker extends TypeVisitor * @param array $suppressed_issues * @param array $phantom_classes */ - public function __construct(private readonly StatementsSource $source, private readonly CodeLocation $code_location, private readonly array $suppressed_issues, private array $phantom_classes = [], private readonly bool $inferred = true, private readonly bool $inherited = false, private bool $prevent_template_covariance = false, private readonly ?string $calling_method_id = null) - { + public function __construct( + private readonly StatementsSource $source, + private readonly CodeLocation $code_location, + private readonly array $suppressed_issues, + private array $phantom_classes = [], + private readonly bool $inferred = true, + private readonly bool $inherited = false, + private bool $prevent_template_covariance = false, + private readonly ?string $calling_method_id = null, + ) { } /** diff --git a/src/Psalm/Internal/TypeVisitor/TypeLocalizer.php b/src/Psalm/Internal/TypeVisitor/TypeLocalizer.php index 57ec6d184e8..dcc40b5451c 100644 --- a/src/Psalm/Internal/TypeVisitor/TypeLocalizer.php +++ b/src/Psalm/Internal/TypeVisitor/TypeLocalizer.php @@ -24,8 +24,10 @@ final class TypeLocalizer extends MutableTypeVisitor /** * @param array> $extends */ - public function __construct(private array $extends, private readonly string $base_fq_class_name) - { + public function __construct( + private array $extends, + private readonly string $base_fq_class_name, + ) { } protected function enterNode(TypeNode &$type): ?int diff --git a/src/Psalm/Internal/TypeVisitor/TypeScanner.php b/src/Psalm/Internal/TypeVisitor/TypeScanner.php index 0a99eab7412..dd480f45b85 100644 --- a/src/Psalm/Internal/TypeVisitor/TypeScanner.php +++ b/src/Psalm/Internal/TypeVisitor/TypeScanner.php @@ -22,8 +22,11 @@ final class TypeScanner extends TypeVisitor /** * @param array $phantom_classes */ - public function __construct(private readonly Scanner $scanner, private readonly ?FileStorage $file_storage, private array $phantom_classes) - { + public function __construct( + private readonly Scanner $scanner, + private readonly ?FileStorage $file_storage, + private array $phantom_classes, + ) { } protected function enterNode(TypeNode $type): ?int diff --git a/src/Psalm/Plugin/ArgTypeInferer.php b/src/Psalm/Plugin/ArgTypeInferer.php index 3bf841fce11..cb70f91a9ca 100644 --- a/src/Psalm/Plugin/ArgTypeInferer.php +++ b/src/Psalm/Plugin/ArgTypeInferer.php @@ -16,8 +16,10 @@ final class ArgTypeInferer /** * @internal */ - public function __construct(private readonly Context $context, private readonly StatementsAnalyzer $statements_analyzer) - { + public function __construct( + private readonly Context $context, + private readonly StatementsAnalyzer $statements_analyzer, + ) { } public function infer(PhpParser\Node\Arg $arg): false|Union diff --git a/src/Psalm/Plugin/DynamicTemplateProvider.php b/src/Psalm/Plugin/DynamicTemplateProvider.php index 80a5a432409..c89821f0612 100644 --- a/src/Psalm/Plugin/DynamicTemplateProvider.php +++ b/src/Psalm/Plugin/DynamicTemplateProvider.php @@ -13,8 +13,9 @@ final class DynamicTemplateProvider /** * @internal */ - public function __construct(private readonly string $defining_class) - { + public function __construct( + private readonly string $defining_class, + ) { } /** diff --git a/src/Psalm/Plugin/EventHandler/Event/AddRemoveTaintsEvent.php b/src/Psalm/Plugin/EventHandler/Event/AddRemoveTaintsEvent.php index 2160228a064..ebcc464615b 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AddRemoveTaintsEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AddRemoveTaintsEvent.php @@ -16,8 +16,12 @@ final class AddRemoveTaintsEvent * * @internal */ - public function __construct(private readonly Expr $expr, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase) - { + public function __construct( + private readonly Expr $expr, + private readonly Context $context, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + ) { } public function getExpr(): Expr diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php index 04d4ec2b49b..977616588bd 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php @@ -16,8 +16,12 @@ final class AfterAnalysisEvent * @param array> $issues where string key is a filepath * @internal */ - public function __construct(private readonly Codebase $codebase, private readonly array $issues, private readonly array $build_info, private readonly ?SourceControlInfo $source_control_info = null) - { + public function __construct( + private readonly Codebase $codebase, + private readonly array $issues, + private readonly array $build_info, + private readonly ?SourceControlInfo $source_control_info = null, + ) { } public function getCodebase(): Codebase diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeAnalysisEvent.php index aa1fe7d4499..20839c14d41 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeAnalysisEvent.php @@ -18,8 +18,13 @@ final class AfterClassLikeAnalysisEvent * @param FileManipulation[] $file_replacements * @internal */ - public function __construct(private readonly Node\Stmt\ClassLike $stmt, private readonly ClassLikeStorage $classlike_storage, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) - { + public function __construct( + private readonly Node\Stmt\ClassLike $stmt, + private readonly ClassLikeStorage $classlike_storage, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements = [], + ) { } public function getStmt(): Node\Stmt\ClassLike diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeExistenceCheckEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeExistenceCheckEvent.php index eccf5ad934a..7e38a0c5a9e 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeExistenceCheckEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeExistenceCheckEvent.php @@ -15,8 +15,13 @@ final class AfterClassLikeExistenceCheckEvent * @param FileManipulation[] $file_replacements * @internal */ - public function __construct(private readonly string $fq_class_name, private readonly CodeLocation $code_location, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) - { + public function __construct( + private readonly string $fq_class_name, + private readonly CodeLocation $code_location, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements = [], + ) { } public function getFqClassName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeVisitEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeVisitEvent.php index 353b0398bd0..e6630ff4bc4 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeVisitEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterClassLikeVisitEvent.php @@ -16,8 +16,13 @@ final class AfterClassLikeVisitEvent * @param FileManipulation[] $file_replacements * @internal */ - public function __construct(private readonly ClassLike $stmt, private readonly ClassLikeStorage $storage, private readonly FileSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) - { + public function __construct( + private readonly ClassLike $stmt, + private readonly ClassLikeStorage $storage, + private readonly FileSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements = [], + ) { } public function getStmt(): ClassLike diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterCodebasePopulatedEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterCodebasePopulatedEvent.php index 02465b295f3..f2bdd176483 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterCodebasePopulatedEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterCodebasePopulatedEvent.php @@ -13,8 +13,9 @@ final class AfterCodebasePopulatedEvent * * @internal */ - public function __construct(private readonly Codebase $codebase) - { + public function __construct( + private readonly Codebase $codebase, + ) { } public function getCodebase(): Codebase diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterEveryFunctionCallAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterEveryFunctionCallAnalysisEvent.php index a85eef0e2c0..e8b098c4d61 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterEveryFunctionCallAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterEveryFunctionCallAnalysisEvent.php @@ -12,8 +12,13 @@ final class AfterEveryFunctionCallAnalysisEvent { /** @internal */ - public function __construct(private readonly FuncCall $expr, private readonly string $function_id, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase) - { + public function __construct( + private readonly FuncCall $expr, + private readonly string $function_id, + private readonly Context $context, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + ) { } public function getExpr(): FuncCall diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterExpressionAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterExpressionAnalysisEvent.php index 6e9f40629f3..a14af785993 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterExpressionAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterExpressionAnalysisEvent.php @@ -18,8 +18,13 @@ final class AfterExpressionAnalysisEvent * @param FileManipulation[] $file_replacements * @internal */ - public function __construct(private readonly Expr $expr, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) - { + public function __construct( + private readonly Expr $expr, + private readonly Context $context, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements = [], + ) { } public function getExpr(): Expr diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterFileAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterFileAnalysisEvent.php index 8713053baf2..915d2efd0bd 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterFileAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterFileAnalysisEvent.php @@ -18,8 +18,13 @@ final class AfterFileAnalysisEvent * @param array $stmts * @internal */ - public function __construct(private readonly StatementsSource $statements_source, private readonly Context $file_context, private readonly FileStorage $file_storage, private readonly Codebase $codebase, private readonly array $stmts) - { + public function __construct( + private readonly StatementsSource $statements_source, + private readonly Context $file_context, + private readonly FileStorage $file_storage, + private readonly Codebase $codebase, + private readonly array $stmts, + ) { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterFunctionCallAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterFunctionCallAnalysisEvent.php index e8c45e0ced5..97f9b1471ec 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterFunctionCallAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterFunctionCallAnalysisEvent.php @@ -18,8 +18,15 @@ final class AfterFunctionCallAnalysisEvent * @param FileManipulation[] $file_replacements * @internal */ - public function __construct(private readonly FuncCall $expr, private readonly string $function_id, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private readonly Union $return_type_candidate, private array $file_replacements) - { + public function __construct( + private readonly FuncCall $expr, + private readonly string $function_id, + private readonly Context $context, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private readonly Union $return_type_candidate, + private array $file_replacements, + ) { } public function getExpr(): FuncCall diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterFunctionLikeAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterFunctionLikeAnalysisEvent.php index a3eaa34869f..527a13dae51 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterFunctionLikeAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterFunctionLikeAnalysisEvent.php @@ -20,8 +20,15 @@ final class AfterFunctionLikeAnalysisEvent * @param FileManipulation[] $file_replacements * @internal */ - public function __construct(private readonly Node\FunctionLike $stmt, private readonly FunctionLikeStorage $functionlike_storage, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements, private readonly NodeTypeProvider $node_type_provider, private readonly Context $context) - { + public function __construct( + private readonly Node\FunctionLike $stmt, + private readonly FunctionLikeStorage $functionlike_storage, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements, + private readonly NodeTypeProvider $node_type_provider, + private readonly Context $context, + ) { } public function getStmt(): Node\FunctionLike diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterMethodCallAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterMethodCallAnalysisEvent.php index 7806ec57289..179e2fb575e 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterMethodCallAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterMethodCallAnalysisEvent.php @@ -19,8 +19,17 @@ final class AfterMethodCallAnalysisEvent * @param FileManipulation[] $file_replacements * @internal */ - public function __construct(private readonly MethodCall|StaticCall $expr, private readonly string $method_id, private readonly string $appearing_method_id, private readonly string $declaring_method_id, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = [], private ?Union $return_type_candidate = null) - { + public function __construct( + private readonly MethodCall|StaticCall $expr, + private readonly string $method_id, + private readonly string $appearing_method_id, + private readonly string $declaring_method_id, + private readonly Context $context, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements = [], + private ?Union $return_type_candidate = null, + ) { } /** diff --git a/src/Psalm/Plugin/EventHandler/Event/AfterStatementAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/AfterStatementAnalysisEvent.php index af07fbb0ba3..9c96b69a59e 100644 --- a/src/Psalm/Plugin/EventHandler/Event/AfterStatementAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/AfterStatementAnalysisEvent.php @@ -18,8 +18,13 @@ final class AfterStatementAnalysisEvent * @param FileManipulation[] $file_replacements * @internal */ - public function __construct(private readonly Stmt $stmt, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) - { + public function __construct( + private readonly Stmt $stmt, + private readonly Context $context, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements = [], + ) { } public function getStmt(): Stmt diff --git a/src/Psalm/Plugin/EventHandler/Event/BeforeAddIssueEvent.php b/src/Psalm/Plugin/EventHandler/Event/BeforeAddIssueEvent.php index 3f1b9685336..d5664a18dd2 100644 --- a/src/Psalm/Plugin/EventHandler/Event/BeforeAddIssueEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/BeforeAddIssueEvent.php @@ -10,8 +10,11 @@ final class BeforeAddIssueEvent { /** @internal */ - public function __construct(private readonly CodeIssue $issue, private readonly bool $fixable, private readonly Codebase $codebase) - { + public function __construct( + private readonly CodeIssue $issue, + private readonly bool $fixable, + private readonly Codebase $codebase, + ) { } public function getIssue(): CodeIssue diff --git a/src/Psalm/Plugin/EventHandler/Event/BeforeExpressionAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/BeforeExpressionAnalysisEvent.php index eb5c0d9f0f7..f3eb1294652 100644 --- a/src/Psalm/Plugin/EventHandler/Event/BeforeExpressionAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/BeforeExpressionAnalysisEvent.php @@ -18,8 +18,13 @@ final class BeforeExpressionAnalysisEvent * @param list $file_replacements * @internal */ - public function __construct(private readonly Expr $expr, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) - { + public function __construct( + private readonly Expr $expr, + private readonly Context $context, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements = [], + ) { } public function getExpr(): Expr diff --git a/src/Psalm/Plugin/EventHandler/Event/BeforeFileAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/BeforeFileAnalysisEvent.php index ef1f722d290..3a2cd512fc7 100644 --- a/src/Psalm/Plugin/EventHandler/Event/BeforeFileAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/BeforeFileAnalysisEvent.php @@ -16,8 +16,12 @@ final class BeforeFileAnalysisEvent * * @internal */ - public function __construct(private readonly StatementsSource $statements_source, private readonly Context $file_context, private readonly FileStorage $file_storage, private readonly Codebase $codebase) - { + public function __construct( + private readonly StatementsSource $statements_source, + private readonly Context $file_context, + private readonly FileStorage $file_storage, + private readonly Codebase $codebase, + ) { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/BeforeStatementAnalysisEvent.php b/src/Psalm/Plugin/EventHandler/Event/BeforeStatementAnalysisEvent.php index d84d2116e2c..7792ec4668a 100644 --- a/src/Psalm/Plugin/EventHandler/Event/BeforeStatementAnalysisEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/BeforeStatementAnalysisEvent.php @@ -18,8 +18,13 @@ final class BeforeStatementAnalysisEvent * @param list $file_replacements * @internal */ - public function __construct(private Stmt $stmt, private readonly Context $context, private readonly StatementsSource $statements_source, private readonly Codebase $codebase, private array $file_replacements = []) - { + public function __construct( + private Stmt $stmt, + private readonly Context $context, + private readonly StatementsSource $statements_source, + private readonly Codebase $codebase, + private array $file_replacements = [], + ) { } public function getStmt(): Stmt diff --git a/src/Psalm/Plugin/EventHandler/Event/DynamicFunctionStorageProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/DynamicFunctionStorageProviderEvent.php index f4ddf2311c0..32246d49e96 100644 --- a/src/Psalm/Plugin/EventHandler/Event/DynamicFunctionStorageProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/DynamicFunctionStorageProviderEvent.php @@ -17,8 +17,15 @@ final class DynamicFunctionStorageProviderEvent /** * @internal */ - public function __construct(private readonly ArgTypeInferer $arg_type_inferer, private readonly DynamicTemplateProvider $template_provider, private readonly StatementsSource $statement_source, private readonly string $function_id, private readonly PhpParser\Node\Expr\FuncCall $func_call, private readonly Context $context, private readonly CodeLocation $code_location) - { + public function __construct( + private readonly ArgTypeInferer $arg_type_inferer, + private readonly DynamicTemplateProvider $template_provider, + private readonly StatementsSource $statement_source, + private readonly string $function_id, + private readonly PhpParser\Node\Expr\FuncCall $func_call, + private readonly Context $context, + private readonly CodeLocation $code_location, + ) { } public function getArgTypeInferer(): ArgTypeInferer diff --git a/src/Psalm/Plugin/EventHandler/Event/FunctionExistenceProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/FunctionExistenceProviderEvent.php index 60b3a7c67fe..77448542420 100644 --- a/src/Psalm/Plugin/EventHandler/Event/FunctionExistenceProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/FunctionExistenceProviderEvent.php @@ -15,8 +15,10 @@ final class FunctionExistenceProviderEvent * * @internal */ - public function __construct(private readonly StatementsSource $statements_source, private readonly string $function_id) - { + public function __construct( + private readonly StatementsSource $statements_source, + private readonly string $function_id, + ) { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/FunctionParamsProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/FunctionParamsProviderEvent.php index c44eafa11bf..e40e26ce96b 100644 --- a/src/Psalm/Plugin/EventHandler/Event/FunctionParamsProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/FunctionParamsProviderEvent.php @@ -15,8 +15,13 @@ final class FunctionParamsProviderEvent * @param list $call_args * @internal */ - public function __construct(private readonly StatementsSource $statements_source, private readonly string $function_id, private readonly array $call_args, private readonly ?Context $context = null, private readonly ?CodeLocation $code_location = null) - { + public function __construct( + private readonly StatementsSource $statements_source, + private readonly string $function_id, + private readonly array $call_args, + private readonly ?Context $context = null, + private readonly ?CodeLocation $code_location = null, + ) { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/FunctionReturnTypeProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/FunctionReturnTypeProviderEvent.php index 10752f816eb..4b108f6d3f8 100644 --- a/src/Psalm/Plugin/EventHandler/Event/FunctionReturnTypeProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/FunctionReturnTypeProviderEvent.php @@ -20,8 +20,13 @@ final class FunctionReturnTypeProviderEvent * @param non-empty-string $function_id * @internal */ - public function __construct(private readonly StatementsSource $statements_source, private readonly string $function_id, private readonly FuncCall $stmt, private readonly Context $context, private readonly CodeLocation $code_location) - { + public function __construct( + private readonly StatementsSource $statements_source, + private readonly string $function_id, + private readonly FuncCall $stmt, + private readonly Context $context, + private readonly CodeLocation $code_location, + ) { } public function getStatementsSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/MethodExistenceProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/MethodExistenceProviderEvent.php index e8e8878b8bb..5d87ecba720 100644 --- a/src/Psalm/Plugin/EventHandler/Event/MethodExistenceProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/MethodExistenceProviderEvent.php @@ -16,8 +16,12 @@ final class MethodExistenceProviderEvent * * @internal */ - public function __construct(private readonly string $fq_classlike_name, private readonly string $method_name_lowercase, private readonly ?StatementsSource $source = null, private readonly ?CodeLocation $code_location = null) - { + public function __construct( + private readonly string $fq_classlike_name, + private readonly string $method_name_lowercase, + private readonly ?StatementsSource $source = null, + private readonly ?CodeLocation $code_location = null, + ) { } public function getFqClasslikeName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/MethodParamsProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/MethodParamsProviderEvent.php index e6d6f097bf6..bcf7d0256a1 100644 --- a/src/Psalm/Plugin/EventHandler/Event/MethodParamsProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/MethodParamsProviderEvent.php @@ -15,8 +15,14 @@ final class MethodParamsProviderEvent * @param list $call_args * @internal */ - public function __construct(private readonly string $fq_classlike_name, private readonly string $method_name_lowercase, private readonly ?array $call_args = null, private readonly ?StatementsSource $statements_source = null, private readonly ?Context $context = null, private readonly ?CodeLocation $code_location = null) - { + public function __construct( + private readonly string $fq_classlike_name, + private readonly string $method_name_lowercase, + private readonly ?array $call_args = null, + private readonly ?StatementsSource $statements_source = null, + private readonly ?Context $context = null, + private readonly ?CodeLocation $code_location = null, + ) { } public function getFqClasslikeName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/MethodReturnTypeProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/MethodReturnTypeProviderEvent.php index 5bad23b0ca7..0338dec8a0c 100644 --- a/src/Psalm/Plugin/EventHandler/Event/MethodReturnTypeProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/MethodReturnTypeProviderEvent.php @@ -22,8 +22,17 @@ final class MethodReturnTypeProviderEvent * @param lowercase-string $called_method_name_lowercase * @internal */ - public function __construct(private readonly StatementsSource $source, private readonly string $fq_classlike_name, private readonly string $method_name_lowercase, private readonly PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $stmt, private readonly Context $context, private readonly CodeLocation $code_location, private readonly ?array $template_type_parameters = null, private readonly ?string $called_fq_classlike_name = null, private readonly ?string $called_method_name_lowercase = null) - { + public function __construct( + private readonly StatementsSource $source, + private readonly string $fq_classlike_name, + private readonly string $method_name_lowercase, + private readonly PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $stmt, + private readonly Context $context, + private readonly CodeLocation $code_location, + private readonly ?array $template_type_parameters = null, + private readonly ?string $called_fq_classlike_name = null, + private readonly ?string $called_method_name_lowercase = null, + ) { } public function getSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/MethodVisibilityProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/MethodVisibilityProviderEvent.php index 125be232acd..17abcadd3b9 100644 --- a/src/Psalm/Plugin/EventHandler/Event/MethodVisibilityProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/MethodVisibilityProviderEvent.php @@ -11,8 +11,13 @@ final class MethodVisibilityProviderEvent { /** @internal */ - public function __construct(private readonly StatementsSource $source, private readonly string $fq_classlike_name, private readonly string $method_name_lowercase, private readonly Context $context, private readonly ?CodeLocation $code_location = null) - { + public function __construct( + private readonly StatementsSource $source, + private readonly string $fq_classlike_name, + private readonly string $method_name_lowercase, + private readonly Context $context, + private readonly ?CodeLocation $code_location = null, + ) { } public function getSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/PropertyExistenceProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/PropertyExistenceProviderEvent.php index 49c76a414b0..a2df1d1774e 100644 --- a/src/Psalm/Plugin/EventHandler/Event/PropertyExistenceProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/PropertyExistenceProviderEvent.php @@ -17,8 +17,14 @@ final class PropertyExistenceProviderEvent * * @internal */ - public function __construct(private readonly string $fq_classlike_name, private readonly string $property_name, private readonly bool $read_mode, private readonly ?StatementsSource $source = null, private readonly ?Context $context = null, private readonly ?CodeLocation $code_location = null) - { + public function __construct( + private readonly string $fq_classlike_name, + private readonly string $property_name, + private readonly bool $read_mode, + private readonly ?StatementsSource $source = null, + private readonly ?Context $context = null, + private readonly ?CodeLocation $code_location = null, + ) { } public function getFqClasslikeName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/PropertyTypeProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/PropertyTypeProviderEvent.php index 78ab0f9f2f3..fd647070031 100644 --- a/src/Psalm/Plugin/EventHandler/Event/PropertyTypeProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/PropertyTypeProviderEvent.php @@ -10,8 +10,13 @@ final class PropertyTypeProviderEvent { /** @internal */ - public function __construct(private readonly string $fq_classlike_name, private readonly string $property_name, private readonly bool $read_mode, private readonly ?StatementsSource $source = null, private readonly ?Context $context = null) - { + public function __construct( + private readonly string $fq_classlike_name, + private readonly string $property_name, + private readonly bool $read_mode, + private readonly ?StatementsSource $source = null, + private readonly ?Context $context = null, + ) { } public function getFqClasslikeName(): string diff --git a/src/Psalm/Plugin/EventHandler/Event/PropertyVisibilityProviderEvent.php b/src/Psalm/Plugin/EventHandler/Event/PropertyVisibilityProviderEvent.php index b0214fb5c49..a566ec8c86c 100644 --- a/src/Psalm/Plugin/EventHandler/Event/PropertyVisibilityProviderEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/PropertyVisibilityProviderEvent.php @@ -11,8 +11,14 @@ final class PropertyVisibilityProviderEvent { /** @internal */ - public function __construct(private readonly StatementsSource $source, private readonly string $fq_classlike_name, private readonly string $property_name, private readonly bool $read_mode, private readonly Context $context, private readonly CodeLocation $code_location) - { + public function __construct( + private readonly StatementsSource $source, + private readonly string $fq_classlike_name, + private readonly string $property_name, + private readonly bool $read_mode, + private readonly Context $context, + private readonly CodeLocation $code_location, + ) { } public function getSource(): StatementsSource diff --git a/src/Psalm/Plugin/EventHandler/Event/StringInterpreterEvent.php b/src/Psalm/Plugin/EventHandler/Event/StringInterpreterEvent.php index 431d316142c..2013ee4a55d 100644 --- a/src/Psalm/Plugin/EventHandler/Event/StringInterpreterEvent.php +++ b/src/Psalm/Plugin/EventHandler/Event/StringInterpreterEvent.php @@ -14,8 +14,10 @@ final class StringInterpreterEvent * @psalm-external-mutation-free * @internal */ - public function __construct(private readonly string $value, private readonly Codebase $codebase) - { + public function __construct( + private readonly string $value, + private readonly Codebase $codebase, + ) { } public function getValue(): string diff --git a/src/Psalm/PluginFileExtensionsSocket.php b/src/Psalm/PluginFileExtensionsSocket.php index ae2e957fc6b..6a0b89b4cac 100644 --- a/src/Psalm/PluginFileExtensionsSocket.php +++ b/src/Psalm/PluginFileExtensionsSocket.php @@ -34,8 +34,9 @@ final class PluginFileExtensionsSocket implements FileExtensionsInterface /** * @internal */ - public function __construct(private readonly Config $config) - { + public function __construct( + private readonly Config $config, + ) { } /** diff --git a/src/Psalm/PluginRegistrationSocket.php b/src/Psalm/PluginRegistrationSocket.php index b91c22d34e7..9523d21d8df 100644 --- a/src/Psalm/PluginRegistrationSocket.php +++ b/src/Psalm/PluginRegistrationSocket.php @@ -26,8 +26,10 @@ final class PluginRegistrationSocket implements RegistrationInterface /** * @internal */ - public function __construct(private readonly Config $config, private readonly Codebase $codebase) - { + public function __construct( + private readonly Config $config, + private readonly Codebase $codebase, + ) { } public function addStubFile(string $file_name): void From 78900857bad01ccd8570c7b14743ae3a904ddf65 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 17:15:26 +0200 Subject: [PATCH 07/63] Fix --- tests/autoload.php | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/autoload.php diff --git a/tests/autoload.php b/tests/autoload.php new file mode 100644 index 00000000000..449bca68efa --- /dev/null +++ b/tests/autoload.php @@ -0,0 +1,9 @@ + Date: Thu, 19 Oct 2023 17:38:56 +0200 Subject: [PATCH 08/63] Fixes --- src/Psalm/CodeLocation.php | 26 +++++++++++++++---- .../Exception/DocblockParseException.php | 2 +- src/Psalm/Internal/Diff/AstDiffer.php | 6 ++--- .../ClassLikeStorageCacheProvider.php | 2 +- .../Provider/FileReferenceCacheProvider.php | 9 ++++--- .../Provider/FileStorageCacheProvider.php | 2 +- .../Internal/Provider/ParserCacheProvider.php | 2 +- .../Provider/ProjectCacheProvider.php | 2 +- 8 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/Psalm/CodeLocation.php b/src/Psalm/CodeLocation.php index b40b2aa528f..8453ce2a588 100644 --- a/src/Psalm/CodeLocation.php +++ b/src/Psalm/CodeLocation.php @@ -51,6 +51,8 @@ class CodeLocation protected int $file_end; + protected bool $single_line; + protected int $preview_start; private int $preview_end = -1; @@ -65,12 +67,20 @@ class CodeLocation private string $snippet = ''; + private ?string $text = null; + public ?int $docblock_start = null; private ?int $docblock_start_line_number = null; + protected ?int $docblock_line_number = null; + + private ?int $regex_type = null; + private bool $have_recalculated = false; + public ?CodeLocation $previous_location = null; + public const VAR_TYPE = 0; public const FUNCTION_RETURN_TYPE = 1; public const FUNCTION_PARAM_TYPE = 2; @@ -83,11 +93,11 @@ class CodeLocation public function __construct( FileSource $file_source, PhpParser\Node $stmt, - public ?CodeLocation $previous_location = null, - protected bool $single_line = false, - private ?int $regex_type = null, - private ?string $text = null, - protected ?int $docblock_line_number = null, + ?CodeLocation $previous_location = null, + bool $single_line = false, + ?int $regex_type = null, + ?string $selected_text = null, + ?int $comment_line = null, ) { /** @psalm-suppress ImpureMethodCall Actually mutation-free just not marked */ $this->file_start = (int)$stmt->getAttribute('startFilePos'); @@ -97,6 +107,10 @@ public function __construct( $this->raw_file_end = $this->file_end; $this->file_path = $file_source->getFilePath(); $this->file_name = $file_source->getFileName(); + $this->single_line = $single_line; + $this->regex_type = $regex_type; + $this->previous_location = $previous_location; + $this->text = $selected_text; /** @psalm-suppress ImpureMethodCall Actually mutation-free just not marked */ $doc_comment = $stmt->getDocComment(); @@ -108,6 +122,8 @@ public function __construct( /** @psalm-suppress ImpureMethodCall Actually mutation-free just not marked */ $this->raw_line_number = $stmt->getLine(); + + $this->docblock_line_number = $comment_line; } /** diff --git a/src/Psalm/Exception/DocblockParseException.php b/src/Psalm/Exception/DocblockParseException.php index 306c7eeb8dc..433f6632d2e 100644 --- a/src/Psalm/Exception/DocblockParseException.php +++ b/src/Psalm/Exception/DocblockParseException.php @@ -6,6 +6,6 @@ use Exception; -final class DocblockParseException extends Exception +class DocblockParseException extends Exception { } diff --git a/src/Psalm/Internal/Diff/AstDiffer.php b/src/Psalm/Internal/Diff/AstDiffer.php index 3c889711585..1e436c0dbf4 100644 --- a/src/Psalm/Internal/Diff/AstDiffer.php +++ b/src/Psalm/Internal/Diff/AstDiffer.php @@ -21,7 +21,7 @@ * * @internal */ -final class AstDiffer +abstract class AstDiffer { /** * @param Closure(Stmt, Stmt, string, string, bool=): bool $is_equal @@ -29,7 +29,7 @@ final class AstDiffer * @param array $b * @return array{0:non-empty-list>, 1: int, 2: int, 3: array} */ - private static function calculateTrace( + protected static function calculateTrace( Closure $is_equal, array $a, array $b, @@ -81,7 +81,7 @@ private static function calculateTrace( * @return list * @psalm-pure */ - private static function extractDiff(array $trace, int $x, int $y, array $a, array $b, array $bc): array + protected static function extractDiff(array $trace, int $x, int $y, array $a, array $b, array $bc): array { $result = []; for ($d = count($trace) - 1; $d >= 0; --$d) { diff --git a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php index 2dfc5736357..c35c5e38238 100644 --- a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php @@ -26,7 +26,7 @@ /** * @internal */ -final class ClassLikeStorageCacheProvider +class ClassLikeStorageCacheProvider { private readonly Cache $cache; diff --git a/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php b/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php index 6a69e2018f3..e91df5dde67 100644 --- a/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php @@ -28,7 +28,7 @@ * @psalm-import-type FileMapType from Analyzer * @internal */ -final class FileReferenceCacheProvider +class FileReferenceCacheProvider { private const REFERENCE_CACHE_NAME = 'references'; private const CLASSLIKE_FILE_CACHE_NAME = 'classlike_files'; @@ -50,10 +50,13 @@ final class FileReferenceCacheProvider private const FILE_MISSING_MEMBER_CACHE_NAME = 'file_missing_member'; private const UNKNOWN_MEMBER_CACHE_NAME = 'unknown_member_references'; private const METHOD_PARAM_USE_CACHE_NAME = 'method_param_uses'; - private readonly Cache $cache; - public function __construct(protected Config $config) + protected Config $config; + protected Cache $cache; + + public function __construct(Config $config) { + $this->config = $config; $this->cache = new Cache($config); } diff --git a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php index 411d79ec9b4..e86503a9192 100644 --- a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php @@ -25,7 +25,7 @@ /** * @internal */ -final class FileStorageCacheProvider +class FileStorageCacheProvider { private string $modified_timestamps = ''; diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index d06376db8db..9e809f4957d 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -38,7 +38,7 @@ /** * @internal */ -final class ParserCacheProvider +class ParserCacheProvider { private const FILE_HASHES = 'file_hashes_json'; private const PARSER_CACHE_DIRECTORY = 'php-parser'; diff --git a/src/Psalm/Internal/Provider/ProjectCacheProvider.php b/src/Psalm/Internal/Provider/ProjectCacheProvider.php index 91bf751fcc5..70167aaf5ad 100644 --- a/src/Psalm/Internal/Provider/ProjectCacheProvider.php +++ b/src/Psalm/Internal/Provider/ProjectCacheProvider.php @@ -22,7 +22,7 @@ * * @internal */ -final class ProjectCacheProvider +class ProjectCacheProvider { private const GOOD_RUN_NAME = 'good_run'; private const COMPOSER_LOCK_HASH = 'composer_lock_hash'; From d5ab48e307111f1d770aa99916b07b723f76d2ee Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 17:45:22 +0200 Subject: [PATCH 09/63] Fix --- tests/PsalmPluginTest.php | 4 ++-- tests/TestConfig.php | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/PsalmPluginTest.php b/tests/PsalmPluginTest.php index 64311a30122..5b97dc23136 100644 --- a/tests/PsalmPluginTest.php +++ b/tests/PsalmPluginTest.php @@ -25,9 +25,9 @@ class PsalmPluginTest extends TestCase { use MockeryPHPUnitIntegration; - private PluginList&MockInterface $plugin_list; + private MockInterface $plugin_list; - private PluginListFactory&MockInterface $plugin_list_factory; + private MockInterface $plugin_list_factory; private Application $app; diff --git a/tests/TestConfig.php b/tests/TestConfig.php index a41360eab81..3e40764af30 100644 --- a/tests/TestConfig.php +++ b/tests/TestConfig.php @@ -61,10 +61,7 @@ protected function getContents(): string '; } - /** - * @return false - */ - public function getComposerFilePathForClassLike(string $fq_classlike_name): bool + public function getComposerFilePathForClassLike(string $fq_classlike_name): false { return false; } From 1cf3233cb635fe31f367f6c142a38b51962a887c Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 17:45:52 +0200 Subject: [PATCH 10/63] Fix --- src/Psalm/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index 4d1361c7bee..9dbceddf36d 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -567,7 +567,7 @@ final class Config public array $config_warnings = []; /** @internal */ - private function __construct() + protected function __construct() { self::$instance = $this; $this->eventDispatcher = new EventDispatcher(); From 3852123903913bac2cb70834a16789ee530a5fa7 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 20:04:00 +0200 Subject: [PATCH 11/63] Fix --- src/Psalm/Codebase.php | 6 +++--- src/Psalm/Config.php | 3 +-- src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php | 4 +++- .../Analyzer/Statements/Block/IfElse/ElseAnalyzer.php | 2 +- .../Analyzer/Statements/Block/IfElse/IfAnalyzer.php | 2 +- .../Internal/Analyzer/Statements/Block/TryAnalyzer.php | 2 +- .../Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php | 2 +- .../Statements/Expression/Call/HighOrderFunctionArgInfo.php | 1 - .../Analyzer/Statements/Expression/Call/NewAnalyzer.php | 2 +- src/Psalm/Internal/Provider/FileStorageCacheProvider.php | 4 ++-- src/Psalm/Internal/Provider/ParserCacheProvider.php | 4 ++-- src/Psalm/Type/Atomic/GenericTrait.php | 4 ++-- src/Psalm/Type/Reconciler.php | 2 +- src/Psalm/Type/UnionTrait.php | 2 +- 14 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Psalm/Codebase.php b/src/Psalm/Codebase.php index dd549856f0a..1fc0d7f165f 100644 --- a/src/Psalm/Codebase.php +++ b/src/Psalm/Codebase.php @@ -99,6 +99,9 @@ use const PHP_VERSION_ID; +/** + * @api + */ final class Codebase { /** @@ -1206,7 +1209,6 @@ public function getSymbolLocationByReference(Reference $reference): ?CodeLocatio } /** - * @psalm-suppress PossiblyUnusedMethod * @return array{0: string, 1: Range}|null */ public function getReferenceAtPosition(string $file_path, Position $position): ?array @@ -2003,7 +2005,6 @@ public function queueClassLikeForScanning( /** * @param array $taints - * @psalm-suppress PossiblyUnusedMethod */ public function addTaintSource( Union $expr_type, @@ -2030,7 +2031,6 @@ public function addTaintSource( /** * @param array $taints - * @psalm-suppress PossiblyUnusedMethod */ public function addTaintSink( string $taint_id, diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index 9dbceddf36d..decd11ce0eb 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -820,7 +820,7 @@ private static function processDeprecatedElement( assert($line > 0); $offset = self::lineNumberToByteOffset($file_contents, $line); - $element_start = strpos($file_contents, (string) $deprecated_element_xml->localName, $offset) ?: 0; + $element_start = strpos($file_contents, $deprecated_element_xml->localName, $offset) ?: 0; $element_end = $element_start + strlen($deprecated_element_xml->localName) - 1; $config->config_issues[] = new ConfigIssue( @@ -875,7 +875,6 @@ private static function processConfigDeprecations( /** * @param non-empty-string $file_contents * @psalm-suppress MixedAssignment - * @psalm-suppress MixedArgument * @psalm-suppress MixedPropertyFetch * @throws ConfigException */ diff --git a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php index 7a9a50bdc25..a887cc6103e 100644 --- a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php @@ -38,7 +38,9 @@ final class NamespaceAnalyzer extends SourceAnalyzer private static array $public_namespace_constants = []; public function __construct( - private readonly Namespace_ $namespace, /** + private readonly Namespace_ $namespace, + /** + * @var FileAnalyzer * @psalm-suppress NonInvariantDocblockPropertyType */ protected SourceAnalyzer $source, diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php index c89173b0371..538fba9af43 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php @@ -82,7 +82,7 @@ public static function analyze( foreach ($changed_var_ids as $changed_var_id => $_) { foreach ($else_context->vars_in_scope as $var_id => $_) { - if (preg_match('/' . preg_quote((string) $changed_var_id, '/') . '[\]\[\-]/', $var_id) + if (preg_match('/' . preg_quote($changed_var_id, '/') . '[\]\[\-]/', $var_id) && !array_key_exists($var_id, $changed_var_ids) ) { $else_context->removePossibleReference($var_id); diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php index 932ad108202..45cc2598001 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php @@ -131,7 +131,7 @@ public static function analyze( foreach ($changed_var_ids as $changed_var_id => $_) { foreach ($if_context->vars_in_scope as $var_id => $_) { - if (preg_match('/' . preg_quote((string) $changed_var_id, '/') . '[\]\[\-]/', $var_id) + if (preg_match('/' . preg_quote($changed_var_id, '/') . '[\]\[\-]/', $var_id) && !array_key_exists($var_id, $changed_var_ids) && !array_key_exists($var_id, $cond_referenced_var_ids) ) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php index eac73b50d57..9222f3109a7 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php @@ -239,7 +239,7 @@ public static function analyze( $fq_catch_class_lower = strtolower($fq_catch_class); foreach ($catch_context->possibly_thrown_exceptions as $exception_fqcln => $_) { - $exception_fqcln_lower = strtolower((string) $exception_fqcln); + $exception_fqcln_lower = strtolower($exception_fqcln); if ($exception_fqcln_lower === $fq_catch_class_lower || ($codebase->classExists($exception_fqcln) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php index e95644d440d..3fbf59c619f 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php @@ -687,7 +687,7 @@ private static function analyzeOperands( && strtolower($non_decimal_type->value) === "decimal\\decimal" ) { $result_type = Type::combineUnionTypes( - new Union([new TNamedObject(Decimal::class)]), + new Union([new TNamedObject("Decimal\\Decimal")]), $result_type, ); } else { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php index 9f5dc9da433..6b3203ab3ba 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php @@ -26,7 +26,6 @@ final class HighOrderFunctionArgInfo * @psalm-param HighOrderFunctionArgInfo::TYPE_* $type */ public function __construct( - /** @psalm-var HighOrderFunctionArgInfo::TYPE_* */ private readonly string $type, private readonly FunctionLikeStorage $function_storage, private readonly ?ClassLikeStorage $class_storage = null, diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php index d8f61a14b2b..b32b19373cb 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php @@ -246,7 +246,7 @@ public static function analyze( new Union([$result_atomic_type]), ); - if (strtolower((string) $fq_class_name) !== 'stdclass' && + if (strtolower($fq_class_name) !== 'stdclass' && $codebase->classlikes->classExists($fq_class_name) ) { self::analyzeNamedConstructor( diff --git a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php index e86503a9192..8419afd80fb 100644 --- a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php @@ -73,7 +73,7 @@ public function writeToCache(FileStorage $storage, string $file_contents): void /** * @param lowercase-string $file_path */ - private function storeInCache(string $file_path, FileStorage $storage): void + protected function storeInCache(string $file_path, FileStorage $storage): void { $cache_location = $this->getCacheLocationForPath($file_path, true); $this->cache->saveItem($cache_location, $storage); @@ -119,7 +119,7 @@ private function getCacheHash(string $_unused_file_path, string $file_contents): /** * @param lowercase-string $file_path */ - private function loadFromCache(string $file_path): ?FileStorage + protected function loadFromCache(string $file_path): ?FileStorage { $storage = $this->cache->getItem($this->getCacheLocationForPath($file_path)); if ($storage instanceof FileStorage) { diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index 9e809f4957d..a54c564f465 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -51,14 +51,14 @@ class ParserCacheProvider * * @var array|null */ - private ?array $existing_file_content_hashes = null; + protected ?array $existing_file_content_hashes = null; /** * A map of recently-added filename hashes to contents hashes * * @var array */ - private array $new_file_content_hashes = []; + protected array $new_file_content_hashes = []; public function __construct( Config $config, diff --git a/src/Psalm/Type/Atomic/GenericTrait.php b/src/Psalm/Type/Atomic/GenericTrait.php index a9c9dc7cac7..e35a72fdfee 100644 --- a/src/Psalm/Type/Atomic/GenericTrait.php +++ b/src/Psalm/Type/Atomic/GenericTrait.php @@ -105,9 +105,9 @@ public function toNamespacedString( return $value_type_string . '[]'; } - $intersection_pos = strpos((string) $base_value, '&'); + $intersection_pos = strpos($base_value, '&'); if ($intersection_pos !== false) { - $base_value = substr((string) $base_value, 0, $intersection_pos); + $base_value = substr($base_value, 0, $intersection_pos); } $type_params = $this->type_params; diff --git a/src/Psalm/Type/Reconciler.php b/src/Psalm/Type/Reconciler.php index ae321e5f2f1..27acdf1b1c4 100644 --- a/src/Psalm/Type/Reconciler.php +++ b/src/Psalm/Type/Reconciler.php @@ -346,7 +346,7 @@ public static function reconcileKeyedTypes( } if (!isset($new_types[$new_key]) - && preg_match('/' . preg_quote($key, '/') . '[\]\[\-]/', (string) $new_key) + && preg_match('/' . preg_quote($key, '/') . '[\]\[\-]/', $new_key) && $is_real ) { // Fix any references to the type before removing it. diff --git a/src/Psalm/Type/UnionTrait.php b/src/Psalm/Type/UnionTrait.php index ad08a02b20a..9506aaa5049 100644 --- a/src/Psalm/Type/UnionTrait.php +++ b/src/Psalm/Type/UnionTrait.php @@ -219,7 +219,7 @@ public function getId(bool $exact = true): string if (count($types) > 1) { foreach ($types as $i => $type) { - if (strpos((string) $type, ' as ') && !str_contains((string) $type, '(')) { + if (strpos($type, ' as ') && !str_contains($type, '(')) { $types[$i] = '(' . $type . ')'; } } From 9ddc39dc73d314c12c28d1913b0eaf1d2e890447 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 20:13:28 +0200 Subject: [PATCH 12/63] Fix --- examples/TemplateScanner.php | 2 +- src/Psalm/Internal/Analyzer/FileAnalyzer.php | 2 +- .../Internal/Analyzer/NamespaceAnalyzer.php | 2 +- .../Block/IfElse/ElseIfAnalyzer.php | 2 +- .../BinaryOp/ArithmeticOpAnalyzer.php | 1 - src/Psalm/Internal/Diff/FileDiffer.php | 2 +- .../LanguageServer/LanguageClient.php | 2 +- .../PhpVisitor/PartialParserVisitor.php | 2 +- src/Psalm/Internal/Type/TypeExpander.php | 22 ---------- src/Psalm/IssueBuffer.php | 1 - src/Psalm/Progress/DefaultProgress.php | 2 +- src/Psalm/Storage/AttributeArg.php | 7 +--- src/Psalm/Storage/AttributeStorage.php | 7 +--- src/Psalm/Type/Atomic/TTypeAlias.php | 42 +------------------ 14 files changed, 11 insertions(+), 85 deletions(-) diff --git a/examples/TemplateScanner.php b/examples/TemplateScanner.php index 254b06dc338..681bf61bdc7 100644 --- a/examples/TemplateScanner.php +++ b/examples/TemplateScanner.php @@ -14,7 +14,7 @@ use function preg_match; use function trim; -final class TemplateScanner extends Psalm\Internal\Scanner\FileScanner +class TemplateScanner extends Psalm\Internal\Scanner\FileScanner { final public const VIEW_CLASS = 'Your\\View\\Class'; diff --git a/src/Psalm/Internal/Analyzer/FileAnalyzer.php b/src/Psalm/Internal/Analyzer/FileAnalyzer.php index 85b2b57592f..f18593633ae 100644 --- a/src/Psalm/Internal/Analyzer/FileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FileAnalyzer.php @@ -41,7 +41,7 @@ * @internal * @psalm-consistent-constructor */ -final class FileAnalyzer extends SourceAnalyzer +class FileAnalyzer extends SourceAnalyzer { use CanAlias; diff --git a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php index a887cc6103e..fb1e9f896e6 100644 --- a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php @@ -38,7 +38,7 @@ final class NamespaceAnalyzer extends SourceAnalyzer private static array $public_namespace_constants = []; public function __construct( - private readonly Namespace_ $namespace, + private readonly Namespace_ $namespace, /** * @var FileAnalyzer * @psalm-suppress NonInvariantDocblockPropertyType diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php index e5e45241fea..da72058bf2c 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php @@ -241,7 +241,7 @@ public static function analyze( foreach ($newly_reconciled_var_ids as $changed_var_id => $_) { foreach ($elseif_context->vars_in_scope as $var_id => $_) { - if (preg_match('/' . preg_quote((string) $changed_var_id, '/') . '[\]\[\-]/', $var_id) + if (preg_match('/' . preg_quote($changed_var_id, '/') . '[\]\[\-]/', $var_id) && !array_key_exists($var_id, $newly_reconciled_var_ids) && !array_key_exists($var_id, $cond_referenced_var_ids) ) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php index 3fbf59c619f..288c3e16cfd 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php @@ -4,7 +4,6 @@ namespace Psalm\Internal\Analyzer\Statements\Expression\BinaryOp; -use Decimal\Decimal; use PhpParser; use Psalm\CodeLocation; use Psalm\Codebase; diff --git a/src/Psalm/Internal/Diff/FileDiffer.php b/src/Psalm/Internal/Diff/FileDiffer.php index e3ce3fbbd32..e6812050b3d 100644 --- a/src/Psalm/Internal/Diff/FileDiffer.php +++ b/src/Psalm/Internal/Diff/FileDiffer.php @@ -250,7 +250,7 @@ public static function getDiff(string $a_code, string $b_code): array $b_offset += $new_text_length; } else { /** @psalm-suppress MixedArgument */ - $same_text_length = strlen((string) $diff_elem->new) + 1; + $same_text_length = strlen($diff_elem->new) + 1; $a_offset += $same_text_length; $b_offset += $same_text_length; diff --git a/src/Psalm/Internal/LanguageServer/LanguageClient.php b/src/Psalm/Internal/LanguageServer/LanguageClient.php index a0b15154a8e..a355c6d9da8 100644 --- a/src/Psalm/Internal/LanguageServer/LanguageClient.php +++ b/src/Psalm/Internal/LanguageServer/LanguageClient.php @@ -153,7 +153,7 @@ private function configurationRefreshed(array $config): void } /** @var array */ - $array = json_decode((string) json_encode($config, JSON_THROW_ON_ERROR), true, 512, JSON_THROW_ON_ERROR); + $array = json_decode(json_encode($config, JSON_THROW_ON_ERROR), true, 512, JSON_THROW_ON_ERROR); if (isset($array['hideWarnings'])) { $this->clientConfiguration->hideWarnings = (bool) $array['hideWarnings']; diff --git a/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php b/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php index 7a8ebe15cdb..19040e27a92 100644 --- a/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php @@ -35,7 +35,7 @@ final class PartialParserVisitor extends PhpParser\NodeVisitorAbstract { private bool $must_rescan = false; - private readonly int $non_method_changes; + private int $non_method_changes; private readonly int $a_file_contents_length; diff --git a/src/Psalm/Internal/Type/TypeExpander.php b/src/Psalm/Internal/Type/TypeExpander.php index 57c7a1eef61..884455268b2 100644 --- a/src/Psalm/Internal/Type/TypeExpander.php +++ b/src/Psalm/Internal/Type/TypeExpander.php @@ -319,28 +319,6 @@ public static function expandAtomic( ]; } - /** @psalm-suppress DeprecatedProperty For backwards compatibility, we have to keep this here. */ - foreach ($return_type->extra_types ?? [] as $alias) { - $more_recursively_fleshed_out_types = self::expandAtomic( - $codebase, - $alias, - $self_class, - $static_class_type, - $parent_class, - $evaluate_class_constants, - $evaluate_conditional_types, - $final, - $expand_generic, - $expand_templates, - $throw_on_unresolvable_constant, - ); - - $recursively_fleshed_out_types = [ - ...$more_recursively_fleshed_out_types, - ...$recursively_fleshed_out_types, - ]; - } - return $recursively_fleshed_out_types; } diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index e2834f1eb37..621a387d9bf 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -881,7 +881,6 @@ public static function getOutput( Report::TYPE_SARIF => new SarifReport($normalized_data, self::$fixable_issue_counts, $report_options), Report::TYPE_CODECLIMATE => new CodeClimateReport($normalized_data, self::$fixable_issue_counts, $report_options), Report::TYPE_COUNT => new CountReport($normalized_data, self::$fixable_issue_counts, $report_options), - default => throw new RuntimeException('Unexpected report format: ' . $report_options->format), }; return $output->create(); diff --git a/src/Psalm/Progress/DefaultProgress.php b/src/Psalm/Progress/DefaultProgress.php index 59381fa938e..57024cbf72f 100644 --- a/src/Psalm/Progress/DefaultProgress.php +++ b/src/Psalm/Progress/DefaultProgress.php @@ -9,7 +9,7 @@ use function str_repeat; use function strlen; -final class DefaultProgress extends LongProgress +class DefaultProgress extends LongProgress { private const TOO_MANY_FILES = 1_500; diff --git a/src/Psalm/Storage/AttributeArg.php b/src/Psalm/Storage/AttributeArg.php index b8fe640932b..edfd57acc1d 100644 --- a/src/Psalm/Storage/AttributeArg.php +++ b/src/Psalm/Storage/AttributeArg.php @@ -10,20 +10,15 @@ /** * @psalm-immutable + * @api */ final class AttributeArg { use ImmutableNonCloneableTrait; public function __construct( - /** - * @psalm-suppress PossiblyUnusedProperty It's part of the public API for now - */ public ?string $name, public Union|UnresolvedConstantComponent $type, - /** - * @psalm-suppress PossiblyUnusedProperty It's part of the public API for now - */ public CodeLocation $location, ) { } diff --git a/src/Psalm/Storage/AttributeStorage.php b/src/Psalm/Storage/AttributeStorage.php index 0e6ad44a31d..3a7ff491a00 100644 --- a/src/Psalm/Storage/AttributeStorage.php +++ b/src/Psalm/Storage/AttributeStorage.php @@ -8,6 +8,7 @@ /** * @psalm-immutable + * @api */ final class AttributeStorage { @@ -19,13 +20,7 @@ final class AttributeStorage public function __construct( public string $fq_class_name, public array $args, - /** - * @psalm-suppress PossiblyUnusedProperty part of public API - */ public CodeLocation $location, - /** - * @psalm-suppress PossiblyUnusedProperty part of public API - */ public CodeLocation $name_location, ) { } diff --git a/src/Psalm/Type/Atomic/TTypeAlias.php b/src/Psalm/Type/Atomic/TTypeAlias.php index f9c27297607..ebda8e4118b 100644 --- a/src/Psalm/Type/Atomic/TTypeAlias.php +++ b/src/Psalm/Type/Atomic/TTypeAlias.php @@ -6,46 +6,17 @@ use Psalm\Type\Atomic; -use function array_map; -use function implode; - /** * @psalm-immutable */ final class TTypeAlias extends Atomic { - /** - * @param array|null $extra_types - */ public function __construct( public string $declaring_fq_classlike_name, - public string $alias_name, /** - * @deprecated type aliases are resolved within {@see TypeParser::resolveTypeAliases()} and therefore the - * referencing type(s) are part of other intersection types. The intersection types are not set anymore - * and with v6 this property along with its related methods will get removed. - */ - public ?array $extra_types = null, + public string $alias_name, ) { parent::__construct(true); } - /** - * @param array|null $extra_types - * @deprecated type aliases are resolved within {@see TypeParser::resolveTypeAliases()} and therefore the - * referencing type(s) are part of other intersection types. This method will get removed with v6. - * @psalm-suppress PossiblyUnusedMethod For backwards compatibility, we have to keep this here. - */ - public function setIntersectionTypes(?array $extra_types): self - { - /** @psalm-suppress DeprecatedProperty For backwards compatibility, we have to keep this here. */ - if ($extra_types === $this->extra_types) { - return $this; - } - return new self( - $this->declaring_fq_classlike_name, - $this->alias_name, - $extra_types, - ); - } public function getKey(bool $include_extra = true): string { @@ -54,17 +25,6 @@ public function getKey(bool $include_extra = true): string public function getId(bool $exact = true, bool $nested = false): string { - /** @psalm-suppress DeprecatedProperty For backwards compatibility, we have to keep this here. */ - if ($this->extra_types) { - return $this->getKey() . '&' . implode( - '&', - array_map( - static fn(Atomic $type): string => $type->getId($exact, true), - $this->extra_types, - ), - ); - } - return $this->getKey(); } From a8ccc92da4138336c8d57dba22c6be7448ab1c08 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 20:16:15 +0200 Subject: [PATCH 13/63] Update --- src/Psalm/Internal/Clause.php | 2 +- src/Psalm/Internal/Fork/PsalmRestarter.php | 6 +++--- src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php | 4 +--- .../Internal/Provider/ClassLikeStorageCacheProvider.php | 4 ++-- src/Psalm/Internal/Provider/FileStorageCacheProvider.php | 8 ++------ src/Psalm/Internal/Provider/ParserCacheProvider.php | 6 +----- src/Psalm/Internal/Provider/ProjectCacheProvider.php | 6 +----- src/Psalm/Internal/Provider/StatementsProvider.php | 6 +----- 8 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/Psalm/Internal/Clause.php b/src/Psalm/Internal/Clause.php index 1e9c7dfbd84..797fb5d3f2c 100644 --- a/src/Psalm/Internal/Clause.php +++ b/src/Psalm/Internal/Clause.php @@ -104,7 +104,7 @@ public function __construct( /** @psalm-suppress ImpureFunctionCall */ $data = serialize($possibility_strings); - $this->hash = PHP_VERSION_ID >= 8_01_00 ? hash('xxh128', $data) : hash('md4', $data); + $this->hash = hash('xxh128', $data); } $this->possibilities = $possibilities; diff --git a/src/Psalm/Internal/Fork/PsalmRestarter.php b/src/Psalm/Internal/Fork/PsalmRestarter.php index 4350badbff6..8c1d6bfa5c7 100644 --- a/src/Psalm/Internal/Fork/PsalmRestarter.php +++ b/src/Psalm/Internal/Fork/PsalmRestarter.php @@ -69,7 +69,7 @@ protected function requiresRestart($default): bool $opcache_loaded = extension_loaded('opcache') || extension_loaded('Zend OPcache'); - if (PHP_VERSION_ID >= 8_00_00 && $opcache_loaded) { + if ($opcache_loaded) { // restart to enable JIT if it's not configured in the optimal way $opcache_settings = [ 'enable_cli' => in_array(ini_get('opcache.enable_cli'), ['1', 'true', true, 1]), @@ -145,11 +145,11 @@ protected function restart($command): void // if it wasn't loaded then we apparently don't have opcache installed and there's no point trying // to tweak it // If we're running on 7.4 there's no JIT available - if (PHP_VERSION_ID >= 8_00_00 && $opcache_loaded) { + if ($opcache_loaded) { $additional_options = [ '-dopcache.enable_cli=true', '-dopcache.jit_buffer_size=512M', - '-dopcache.jit=1205', + '-dopcache.jit=tracing', '-dopcache.optimization_level=0x7FFEBFFF', '-dopcache.preload=', '-dopcache.log_verbosity_level=0', diff --git a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php index fd95f55faf0..4497963b47c 100644 --- a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php @@ -210,9 +210,7 @@ public function enterNode(PhpParser\Node $node): ?int $classlike_storage->class_implements['stringable'] = 'Stringable'; } - if (PHP_VERSION_ID >= 8_00_00) { - $this->codebase->scanner->queueClassLikeForScanning('Stringable'); - } + $this->codebase->scanner->queueClassLikeForScanning('Stringable'); } if (!$this->scan_deep) { diff --git a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php index c35c5e38238..75863abd86a 100644 --- a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php @@ -106,7 +106,7 @@ public function getLatestFromCache( private function getCacheHash(?string $_unused_file_path, ?string $file_contents): string { $data = $file_contents ?: $this->modified_timestamps; - return PHP_VERSION_ID >= 8_01_00 ? hash('xxh128', $data) : hash('md4', $data); + return hash('xxh128', $data); } private function loadFromCache(string $fq_classlike_name_lc, ?string $file_path): ?ClassLikeStorage @@ -152,7 +152,7 @@ private function getCacheLocationForClass( $data = $file_path ? strtolower($file_path) . ' ' : ''; $data .= $fq_classlike_name_lc; - $file_path_sha = PHP_VERSION_ID >= 8_01_00 ? hash('xxh128', $data) : hash('md4', $data); + $file_path_sha = hash('xxh128', $data); return $parser_cache_directory . DIRECTORY_SEPARATOR diff --git a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php index 8419afd80fb..e766769d708 100644 --- a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php @@ -113,7 +113,7 @@ private function getCacheHash(string $_unused_file_path, string $file_contents): // the timestamp is only needed if we don't have file contents // as same contents should give same results, independent of when file was modified $data = $file_contents ?: $this->modified_timestamps; - return PHP_VERSION_ID >= 8_01_00 ? hash('xxh128', $data) : hash('md4', $data); + return hash('xxh128', $data); } /** @@ -157,11 +157,7 @@ private function getCacheLocationForPath(string $file_path, bool $create_directo } } - if (PHP_VERSION_ID >= 8_01_00) { - $hash = hash('xxh128', $file_path); - } else { - $hash = hash('md4', $file_path); - } + $hash = hash('xxh128', $file_path); return $parser_cache_directory . DIRECTORY_SEPARATOR diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index a54c564f465..2125c190f49 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -332,11 +332,7 @@ public function deleteOldParserCaches(float $time_before): int private function getParserCacheKey(string $file_path): string { - if (PHP_VERSION_ID >= 8_01_00) { - $hash = hash('xxh128', $file_path); - } else { - $hash = hash('md4', $file_path); - } + $hash = hash('xxh128', $file_path); return $hash . ($this->cache->use_igbinary ? '-igbinary' : '') . '-r'; } diff --git a/src/Psalm/Internal/Provider/ProjectCacheProvider.php b/src/Psalm/Internal/Provider/ProjectCacheProvider.php index 70167aaf5ad..0a162b94f0b 100644 --- a/src/Psalm/Internal/Provider/ProjectCacheProvider.php +++ b/src/Psalm/Internal/Provider/ProjectCacheProvider.php @@ -84,11 +84,7 @@ public function hasLockfileChanged(): bool return true; } - if (PHP_VERSION_ID >= 8_01_00) { - $hash = hash('xxh128', $lockfile_contents); - } else { - $hash = hash('md4', $lockfile_contents); - } + $hash = hash('xxh128', $lockfile_contents); } else { $hash = ''; } diff --git a/src/Psalm/Internal/Provider/StatementsProvider.php b/src/Psalm/Internal/Provider/StatementsProvider.php index b171cd645f1..471632e1314 100644 --- a/src/Psalm/Internal/Provider/StatementsProvider.php +++ b/src/Psalm/Internal/Provider/StatementsProvider.php @@ -111,11 +111,7 @@ public function getStatementsForFile( $config = Config::getInstance(); - if (PHP_VERSION_ID >= 8_01_00) { - $file_content_hash = hash('xxh128', $version . $file_contents); - } else { - $file_content_hash = hash('md4', $version . $file_contents); - } + $file_content_hash = hash('xxh128', $version . $file_contents); if (!$this->parser_cache_provider || (!$config->isInProjectDirs($file_path) && strpos($file_path, 'vendor')) From 34b427286a28d0de0e5514de9d9756bcfa7e391b Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 20:41:14 +0200 Subject: [PATCH 14/63] Fixup --- .../Statements/Expression/AssertionFinder.php | 30 ++++++++++++------- .../Expression/AssignmentAnalyzer.php | 4 +-- .../Statements/ExpressionAnalyzer.php | 2 +- src/Psalm/Internal/Clause.php | 2 -- src/Psalm/Internal/Cli/Psalm.php | 2 +- src/Psalm/Internal/Fork/PsalmRestarter.php | 2 -- .../Internal/PhpVisitor/ReflectorVisitor.php | 2 -- .../ClassLikeStorageCacheProvider.php | 1 - .../Provider/FileStorageCacheProvider.php | 1 - .../Internal/Provider/ParserCacheProvider.php | 1 - .../Provider/ProjectCacheProvider.php | 1 - .../Internal/Provider/StatementsProvider.php | 2 -- src/Psalm/Plugin/ArgTypeInferer.php | 4 +-- 13 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php index 79e102de0e5..9afa824beb6 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php @@ -1386,10 +1386,11 @@ private static function hasEmptyArrayVariable( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional + * @return false|int */ private static function hasGetTypeCheck( PhpParser\Node\Expr\BinaryOp $conditional, - ): false|int { + ): bool|int { if ($conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name && strtolower($conditional->right->name->getFirst()) === 'gettype' @@ -1413,10 +1414,11 @@ private static function hasGetTypeCheck( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional + * @return false|int */ private static function hasGetDebugTypeCheck( PhpParser\Node\Expr\BinaryOp $conditional, - ): false|int { + ): bool|int { if ($conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name && strtolower($conditional->right->name->getFirst()) === 'get_debug_type' @@ -1442,11 +1444,12 @@ private static function hasGetDebugTypeCheck( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional + * @return false|int */ private static function hasGetClassCheck( PhpParser\Node\Expr\BinaryOp $conditional, FileSource $source, - ): false|int { + ): bool|int { if (!$source instanceof StatementsAnalyzer) { return false; } @@ -1534,11 +1537,12 @@ private static function hasGetClassCheck( /** * @param Greater|GreaterOrEqual|Smaller|SmallerOrEqual $conditional + * @return false|int */ private static function hasNonEmptyCountEqualityCheck( PhpParser\Node\Expr\BinaryOp $conditional, ?int &$min_count, - ): false|int { + ): bool|int { if ($conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) @@ -1575,11 +1579,12 @@ private static function hasNonEmptyCountEqualityCheck( /** * @param Greater|GreaterOrEqual|Smaller|SmallerOrEqual $conditional + * @return false|int */ private static function hasLessThanCountEqualityCheck( PhpParser\Node\Expr\BinaryOp $conditional, ?int &$max_count, - ): false|int { + ): bool|int { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) @@ -1623,11 +1628,12 @@ private static function hasLessThanCountEqualityCheck( /** * @param Equal|Identical|NotEqual|NotIdentical $conditional + * @return false|int */ private static function hasCountEqualityCheck( PhpParser\Node\Expr\BinaryOp $conditional, ?int &$count, - ): false|int { + ): bool|int { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) @@ -1655,12 +1661,13 @@ private static function hasCountEqualityCheck( /** * @param PhpParser\Node\Expr\BinaryOp\Greater|PhpParser\Node\Expr\BinaryOp\GreaterOrEqual $conditional + * @return false|int */ private static function hasSuperiorNumberCheck( FileSource $source, PhpParser\Node\Expr\BinaryOp $conditional, ?int &$literal_value_comparison, - ): false|int { + ): bool|int { $right_assignment = false; $value_right = null; if ($source instanceof StatementsAnalyzer @@ -1714,12 +1721,13 @@ private static function hasSuperiorNumberCheck( /** * @param PhpParser\Node\Expr\BinaryOp\Smaller|PhpParser\Node\Expr\BinaryOp\SmallerOrEqual $conditional + * @return false|int */ private static function hasInferiorNumberCheck( FileSource $source, PhpParser\Node\Expr\BinaryOp $conditional, ?int &$literal_value_comparison, - ): false|int { + ): bool|int { $right_assignment = false; $value_right = null; if ($source instanceof StatementsAnalyzer @@ -1773,10 +1781,11 @@ private static function hasInferiorNumberCheck( /** * @param PhpParser\Node\Expr\BinaryOp\Greater|PhpParser\Node\Expr\BinaryOp\GreaterOrEqual $conditional + * @return false|int */ private static function hasReconcilableNonEmptyCountEqualityCheck( PhpParser\Node\Expr\BinaryOp $conditional, - ): false|int { + ): bool|int { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']); @@ -1794,11 +1803,12 @@ private static function hasReconcilableNonEmptyCountEqualityCheck( /** * @param Identical|Equal|NotIdentical|NotEqual $conditional + * @return false|int */ private static function hasTypedValueComparison( PhpParser\Node\Expr\BinaryOp $conditional, FileSource $source, - ): false|int { + ): bool|int { if (!$source instanceof StatementsAnalyzer) { return false; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php index aea4fba535e..baa0c6e7283 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php @@ -114,7 +114,7 @@ public static function analyze( ?PhpParser\Comment\Doc $doc_comment, array $not_ignored_docblock_var_ids = [], ?PhpParser\Node\Expr $assign_expr = null, - ): false|Union { + ): ?Union { $var_id = ExpressionIdentifier::getVarId( $assign_var, $statements_analyzer->getFQCLN(), @@ -680,7 +680,7 @@ private static function analyzeAssignment( $assign_value, $assign_value_type, $context, - ) === false) { + ) === null) { return false; } } diff --git a/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php index 3fdf106e218..7b167153efd 100644 --- a/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php @@ -536,7 +536,7 @@ private static function analyzeAssignment( !$from_stmt ? $stmt : null, ); - if ($assignment_type === false) { + if ($assignment_type === null) { return false; } diff --git a/src/Psalm/Internal/Clause.php b/src/Psalm/Internal/Clause.php index 797fb5d3f2c..31c8e2804b0 100644 --- a/src/Psalm/Internal/Clause.php +++ b/src/Psalm/Internal/Clause.php @@ -24,8 +24,6 @@ use function serialize; use function substr; -use const PHP_VERSION_ID; - /** * @internal * @psalm-immutable diff --git a/src/Psalm/Internal/Cli/Psalm.php b/src/Psalm/Internal/Cli/Psalm.php index 88a8fa895ac..5aee0ced16d 100644 --- a/src/Psalm/Internal/Cli/Psalm.php +++ b/src/Psalm/Internal/Cli/Psalm.php @@ -1118,7 +1118,7 @@ private static function storeFlowGraph(array $options, ProjectAnalyzer $project_ } /** @return false|'always'|'auto' */ - private static function shouldFindUnusedCode(array $options, Config $config): false|string + private static function shouldFindUnusedCode(array $options, Config $config): bool|string { $find_unused_code = false; if (isset($options['find-dead-code'])) { diff --git a/src/Psalm/Internal/Fork/PsalmRestarter.php b/src/Psalm/Internal/Fork/PsalmRestarter.php index 8c1d6bfa5c7..69b6089cfe0 100644 --- a/src/Psalm/Internal/Fork/PsalmRestarter.php +++ b/src/Psalm/Internal/Fork/PsalmRestarter.php @@ -20,8 +20,6 @@ use function strlen; use function strtolower; -use const PHP_VERSION_ID; - /** * @internal */ diff --git a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php index 4497963b47c..bc911d8cd6f 100644 --- a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php @@ -46,8 +46,6 @@ use function strpos; use function strtolower; -use const PHP_VERSION_ID; - /** * @internal */ diff --git a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php index 75863abd86a..73975ea2110 100644 --- a/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php @@ -21,7 +21,6 @@ use function strtolower; use const DIRECTORY_SEPARATOR; -use const PHP_VERSION_ID; /** * @internal diff --git a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php index e766769d708..ee02fadad81 100644 --- a/src/Psalm/Internal/Provider/FileStorageCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileStorageCacheProvider.php @@ -20,7 +20,6 @@ use function strtolower; use const DIRECTORY_SEPARATOR; -use const PHP_VERSION_ID; /** * @internal diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php index 2125c190f49..0c6bba2af47 100644 --- a/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -32,7 +32,6 @@ use const DIRECTORY_SEPARATOR; use const JSON_THROW_ON_ERROR; use const LOCK_EX; -use const PHP_VERSION_ID; use const SCANDIR_SORT_NONE; /** diff --git a/src/Psalm/Internal/Provider/ProjectCacheProvider.php b/src/Psalm/Internal/Provider/ProjectCacheProvider.php index 0a162b94f0b..6200430f8dd 100644 --- a/src/Psalm/Internal/Provider/ProjectCacheProvider.php +++ b/src/Psalm/Internal/Provider/ProjectCacheProvider.php @@ -14,7 +14,6 @@ use function touch; use const DIRECTORY_SEPARATOR; -use const PHP_VERSION_ID; /** * Used to determine which files reference other files, necessary for using the --diff diff --git a/src/Psalm/Internal/Provider/StatementsProvider.php b/src/Psalm/Internal/Provider/StatementsProvider.php index 471632e1314..b5bdbef8ac1 100644 --- a/src/Psalm/Internal/Provider/StatementsProvider.php +++ b/src/Psalm/Internal/Provider/StatementsProvider.php @@ -37,8 +37,6 @@ use function strlen; use function strpos; -use const PHP_VERSION_ID; - /** * @internal */ diff --git a/src/Psalm/Plugin/ArgTypeInferer.php b/src/Psalm/Plugin/ArgTypeInferer.php index cb70f91a9ca..109769c8024 100644 --- a/src/Psalm/Plugin/ArgTypeInferer.php +++ b/src/Psalm/Plugin/ArgTypeInferer.php @@ -22,7 +22,7 @@ public function __construct( ) { } - public function infer(PhpParser\Node\Arg $arg): false|Union + public function infer(PhpParser\Node\Arg $arg): null|Union { $already_inferred_type = $this->statements_analyzer->node_data->getType($arg->value); @@ -31,7 +31,7 @@ public function infer(PhpParser\Node\Arg $arg): false|Union } if (ExpressionAnalyzer::analyze($this->statements_analyzer, $arg->value, $this->context) === false) { - return false; + return null; } return $this->statements_analyzer->node_data->getType($arg->value) ?? Type::getMixed(); From f3c61932500b6a5aea744a4b49840dbc3d7955b1 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 20:56:29 +0200 Subject: [PATCH 15/63] Fix --- .../Expression/AssignmentAnalyzer.php | 14 +++--- src/Psalm/Internal/Fork/PsalmRestarter.php | 50 +++++++++++-------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php index baa0c6e7283..01ff31099e8 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php @@ -258,7 +258,7 @@ public static function analyze( $context->vars_in_scope[$var_id] = $comment_type ?? Type::getMixed(); } - return false; + return null; } $context->inside_general_use = $was_inside_general_use; @@ -480,7 +480,7 @@ public static function analyze( ), $statements_analyzer->getSuppressedIssues(), )) { - return false; + return null; } if (isset($context->protected_var_ids[$var_id]) @@ -507,9 +507,9 @@ public static function analyze( $extended_var_id, $var_comments, $removed_taints, - ) === false + ) === null ) { - return false; + return null; } if ($var_id && isset($context->vars_in_scope[$var_id])) { @@ -537,7 +537,7 @@ public static function analyze( ), $statements_analyzer->getSuppressedIssues(), )) { - return false; + return null; } $context->vars_in_scope[$var_id] = Type::getNever(); @@ -670,7 +670,7 @@ private static function analyzeAssignment( $assign_var->class instanceof PhpParser\Node\Name ) { if (ExpressionAnalyzer::analyze($statements_analyzer, $assign_var, $context) === false) { - return false; + return null; } if ($context->check_classes) { @@ -681,7 +681,7 @@ private static function analyzeAssignment( $assign_value_type, $context, ) === null) { - return false; + return null; } } diff --git a/src/Psalm/Internal/Fork/PsalmRestarter.php b/src/Psalm/Internal/Fork/PsalmRestarter.php index 69b6089cfe0..30f8e234d44 100644 --- a/src/Psalm/Internal/Fork/PsalmRestarter.php +++ b/src/Psalm/Internal/Fork/PsalmRestarter.php @@ -16,6 +16,7 @@ use function implode; use function in_array; use function ini_get; +use function is_int; use function preg_replace; use function strlen; use function strtolower; @@ -26,9 +27,22 @@ final class PsalmRestarter extends XdebugHandler { private const REQUIRED_OPCACHE_SETTINGS = [ - 'enable_cli' => true, - 'jit' => 1205, + 'enable_cli' => 1, + 'jit' => 1254, + 'validate_timestamps' => 0, + 'file_update_protection' => 0, 'jit_buffer_size' => 512 * 1024 * 1024, + 'max_accelerated_files' => 1000000, + 'interned_strings_buffer' => 64, + 'jit_max_root_traces' => 30000000, + 'jit_max_side_traces' => 30000000, + 'jit_max_exit_counters' => 30000000, + 'jit_hot_loop' => 1, + 'jit_hot_func' => 1, + 'jit_hot_return' => 1, + 'jit_hot_side_exit' => 1, + 'jit_blacklist_root_trace' => 255, + 'jit_blacklist_side_trace' => 255, 'optimization_level' => '0x7FFEBFFF', 'preload' => '', 'log_verbosity_level' => 0, @@ -69,17 +83,16 @@ protected function requiresRestart($default): bool if ($opcache_loaded) { // restart to enable JIT if it's not configured in the optimal way - $opcache_settings = [ - 'enable_cli' => in_array(ini_get('opcache.enable_cli'), ['1', 'true', true, 1]), - 'jit' => (int) ini_get('opcache.jit'), - 'log_verbosity_level' => (int) ini_get('opcache.log_verbosity_level'), - 'optimization_level' => (string) ini_get('opcache.optimization_level'), - 'preload' => (string) ini_get('opcache.preload'), - 'jit_buffer_size' => self::toBytes((string) ini_get('opcache.jit_buffer_size')), - ]; - foreach (self::REQUIRED_OPCACHE_SETTINGS as $ini_name => $required_value) { - if ($opcache_settings[$ini_name] !== $required_value) { + $value = (string) ini_get("opcache.$ini_name"); + if ($ini_name === 'jit_buffer_size') { + $value = self::toBytes($value); + } elseif ($ini_name === 'enable_cli') { + $value = in_array($value, ['1', 'true', true, 1]); + } elseif (is_int($required_value)) { + $required_value = (int) $required_value; + } + if ($value !== $required_value) { return true; } } @@ -142,16 +155,11 @@ protected function restart($command): void // executed in the parent process (before restart) // if it wasn't loaded then we apparently don't have opcache installed and there's no point trying // to tweak it - // If we're running on 7.4 there's no JIT available if ($opcache_loaded) { - $additional_options = [ - '-dopcache.enable_cli=true', - '-dopcache.jit_buffer_size=512M', - '-dopcache.jit=tracing', - '-dopcache.optimization_level=0x7FFEBFFF', - '-dopcache.preload=', - '-dopcache.log_verbosity_level=0', - ]; + $additional_options = []; + foreach (self::REQUIRED_OPCACHE_SETTINGS as $key => $value) { + $additional_options []= "-dopcache.{$key}={$value}"; + } } array_splice( From 887d2ff17129e3a09bd615331caed5ce6200da8c Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 21:26:08 +0200 Subject: [PATCH 16/63] Fix --- .../Analyzer/Statements/Expression/AssignmentAnalyzer.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php index 01ff31099e8..206bd400353 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php @@ -507,7 +507,7 @@ public static function analyze( $extended_var_id, $var_comments, $removed_taints, - ) === null + ) === false ) { return null; } @@ -670,7 +670,7 @@ private static function analyzeAssignment( $assign_var->class instanceof PhpParser\Node\Name ) { if (ExpressionAnalyzer::analyze($statements_analyzer, $assign_var, $context) === false) { - return null; + return false; } if ($context->check_classes) { @@ -680,8 +680,8 @@ private static function analyzeAssignment( $assign_value, $assign_value_type, $context, - ) === null) { - return null; + ) === false) { + return false; } } From 69cddcf0f6cef818ca1283e5d8436c3bfef8adca Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 21:30:18 +0200 Subject: [PATCH 17/63] Update --- tests/TestConfig.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/TestConfig.php b/tests/TestConfig.php index 3e40764af30..87433cc67c6 100644 --- a/tests/TestConfig.php +++ b/tests/TestConfig.php @@ -61,7 +61,8 @@ protected function getContents(): string '; } - public function getComposerFilePathForClassLike(string $fq_classlike_name): false + /** @return false */ + public function getComposerFilePathForClassLike(string $fq_classlike_name): bool { return false; } From 9d3fee47afa90f3eb53043a26f01e587d2dd34e5 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 19 Oct 2023 21:33:05 +0200 Subject: [PATCH 18/63] Fix --- src/Psalm/Config.php | 3 ++- src/Psalm/Internal/Provider/FileReferenceCacheProvider.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index decd11ce0eb..8759c0ddbcd 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -2324,7 +2324,8 @@ public function visitComposerAutoloadFiles(ProjectAnalyzer $project_analyzer, ?P } } - public function getComposerFilePathForClassLike(string $fq_classlike_name): string|false + /** @return string|false */ + public function getComposerFilePathForClassLike(string $fq_classlike_name): string|bool { if (!$this->composer_class_loader) { return false; diff --git a/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php b/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php index e91df5dde67..fefb161bce5 100644 --- a/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php +++ b/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php @@ -285,7 +285,8 @@ public function setTypeCoverage(array $mixed_counts): void $this->saveCacheItem(self::TYPE_COVERAGE_CACHE_NAME, $mixed_counts); } - public function getConfigHashCache(): string|false + /** @return string|false */ + public function getConfigHashCache(): string|bool { $cache_directory = $this->config->getCacheDirectory(); From dd2d3a286b2ad0d2cc749321c4afb54c3a8273d2 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 20 Oct 2023 11:32:03 +0200 Subject: [PATCH 19/63] Fixes --- src/Psalm/Internal/Codebase/Analyzer.php | 6 +++--- src/Psalm/Internal/Codebase/Scanner.php | 2 +- .../Internal/Provider/DynamicFunctionStorageProvider.php | 2 +- src/Psalm/Internal/Provider/PropertyVisibilityProvider.php | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php index eb217fe09d0..843316f12e9 100644 --- a/src/Psalm/Internal/Codebase/Analyzer.php +++ b/src/Psalm/Internal/Codebase/Analyzer.php @@ -321,9 +321,9 @@ private function doAnalysis(ProjectAnalyzer $project_analyzer, int $pool_size): $codebase = $project_analyzer->getCodebase(); - $analysis_worker = Closure::fromCallable($this->analysisWorker(...)); + $analysis_worker = $this->analysisWorker(...); - $task_done_closure = Closure::fromCallable($this->taskDoneClosure(...)); + $task_done_closure = $this->taskDoneClosure(...); if ($pool_size > 1 && count($this->files_to_analyze) > $pool_size) { $shuffle_count = $pool_size + 1; @@ -385,7 +385,7 @@ static function (): void { $file_reference_provider->setMethodParamUses([]); }, $analysis_worker, - Closure::fromCallable($this->getWorkerData(...)), + $this->getWorkerData(...), $task_done_closure, ); diff --git a/src/Psalm/Internal/Codebase/Scanner.php b/src/Psalm/Internal/Codebase/Scanner.php index 04ccb83895b..58269f66544 100644 --- a/src/Psalm/Internal/Codebase/Scanner.php +++ b/src/Psalm/Internal/Codebase/Scanner.php @@ -329,7 +329,7 @@ function (): void { $this->progress->debug('Have initialised forked process for scanning' . PHP_EOL); }, - Closure::fromCallable($this->scanAPath(...)), + $this->scanAPath(...), /** * @return PoolData */ diff --git a/src/Psalm/Internal/Provider/DynamicFunctionStorageProvider.php b/src/Psalm/Internal/Provider/DynamicFunctionStorageProvider.php index 3f0aca0ec03..9babb09b7c4 100644 --- a/src/Psalm/Internal/Provider/DynamicFunctionStorageProvider.php +++ b/src/Psalm/Internal/Provider/DynamicFunctionStorageProvider.php @@ -37,7 +37,7 @@ final class DynamicFunctionStorageProvider */ public function registerClass(string $class): void { - $callable = Closure::fromCallable([$class, 'getFunctionStorage']); + $callable = $class::getFunctionStorage(...); foreach ($class::getFunctionIds() as $function_id) { $this->registerClosure($function_id, $callable); diff --git a/src/Psalm/Internal/Provider/PropertyVisibilityProvider.php b/src/Psalm/Internal/Provider/PropertyVisibilityProvider.php index 1af11782fa5..a9176a4fec2 100644 --- a/src/Psalm/Internal/Provider/PropertyVisibilityProvider.php +++ b/src/Psalm/Internal/Provider/PropertyVisibilityProvider.php @@ -36,7 +36,7 @@ public function __construct() */ public function registerClass(string $class): void { - $callable = Closure::fromCallable([$class, 'isPropertyVisible']); + $callable = $class::isPropertyVisible(...); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); From c88fa5ccab2bf7735d9dda666664f1198610b3a5 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 20 Oct 2023 11:34:41 +0200 Subject: [PATCH 20/63] Fix --- src/Psalm/Internal/Provider/FunctionExistenceProvider.php | 2 +- src/Psalm/Internal/Provider/FunctionParamsProvider.php | 2 +- src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php | 2 +- src/Psalm/Internal/Provider/MethodExistenceProvider.php | 2 +- src/Psalm/Internal/Provider/MethodParamsProvider.php | 2 +- src/Psalm/Internal/Provider/MethodReturnTypeProvider.php | 2 +- src/Psalm/Internal/Provider/MethodVisibilityProvider.php | 2 +- src/Psalm/Internal/Provider/PropertyExistenceProvider.php | 2 +- src/Psalm/Internal/Provider/PropertyTypeProvider.php | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Psalm/Internal/Provider/FunctionExistenceProvider.php b/src/Psalm/Internal/Provider/FunctionExistenceProvider.php index f5527c98075..7e84726d4e5 100644 --- a/src/Psalm/Internal/Provider/FunctionExistenceProvider.php +++ b/src/Psalm/Internal/Provider/FunctionExistenceProvider.php @@ -36,7 +36,7 @@ public function __construct() public function registerClass(string $class): void { if (is_subclass_of($class, FunctionExistenceProviderInterface::class, true)) { - $callable = Closure::fromCallable([$class, 'doesFunctionExist']); + $callable = $class::doesFunctionExist(...); foreach ($class::getFunctionIds() as $function_id) { $this->registerClosure($function_id, $callable); diff --git a/src/Psalm/Internal/Provider/FunctionParamsProvider.php b/src/Psalm/Internal/Provider/FunctionParamsProvider.php index 976b8033f90..ce852dc887c 100644 --- a/src/Psalm/Internal/Provider/FunctionParamsProvider.php +++ b/src/Psalm/Internal/Provider/FunctionParamsProvider.php @@ -38,7 +38,7 @@ public function __construct() */ public function registerClass(string $class): void { - $callable = Closure::fromCallable([$class, 'getFunctionParams']); + $callable = $class::getFunctionParams(...); foreach ($class::getFunctionIds() as $function_id) { $this->registerClosure($function_id, $callable); diff --git a/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php b/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php index de3a11462b6..228010cb8ea 100644 --- a/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php @@ -117,7 +117,7 @@ public function __construct() public function registerClass(string $class): void { if (is_subclass_of($class, FunctionReturnTypeProviderInterface::class, true)) { - $callable = Closure::fromCallable([$class, 'getFunctionReturnType']); + $callable = $class::getFunctionReturnType(...); foreach ($class::getFunctionIds() as $function_id) { $this->registerClosure($function_id, $callable); diff --git a/src/Psalm/Internal/Provider/MethodExistenceProvider.php b/src/Psalm/Internal/Provider/MethodExistenceProvider.php index 657fddd0de5..af345f77e3e 100644 --- a/src/Psalm/Internal/Provider/MethodExistenceProvider.php +++ b/src/Psalm/Internal/Provider/MethodExistenceProvider.php @@ -35,7 +35,7 @@ public function __construct() */ public function registerClass(string $class): void { - $callable = Closure::fromCallable([$class, 'doesMethodExist']); + $callable = $class::doesMethodExist(...); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); diff --git a/src/Psalm/Internal/Provider/MethodParamsProvider.php b/src/Psalm/Internal/Provider/MethodParamsProvider.php index 58e225b787a..8599c4b2916 100644 --- a/src/Psalm/Internal/Provider/MethodParamsProvider.php +++ b/src/Psalm/Internal/Provider/MethodParamsProvider.php @@ -44,7 +44,7 @@ public function __construct() public function registerClass(string $class): void { if (is_subclass_of($class, MethodParamsProviderInterface::class, true)) { - $callable = Closure::fromCallable([$class, 'getMethodParams']); + $callable = $class::getMethodParams(...); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); diff --git a/src/Psalm/Internal/Provider/MethodReturnTypeProvider.php b/src/Psalm/Internal/Provider/MethodReturnTypeProvider.php index 575b257caa3..1e57683a2ea 100644 --- a/src/Psalm/Internal/Provider/MethodReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/MethodReturnTypeProvider.php @@ -51,7 +51,7 @@ public function __construct() public function registerClass(string $class): void { if (is_subclass_of($class, MethodReturnTypeProviderInterface::class, true)) { - $callable = Closure::fromCallable([$class, 'getMethodReturnType']); + $callable = $class::getMethodReturnType(...); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); diff --git a/src/Psalm/Internal/Provider/MethodVisibilityProvider.php b/src/Psalm/Internal/Provider/MethodVisibilityProvider.php index fcda0291d9c..a9d88825641 100644 --- a/src/Psalm/Internal/Provider/MethodVisibilityProvider.php +++ b/src/Psalm/Internal/Provider/MethodVisibilityProvider.php @@ -39,7 +39,7 @@ public function __construct() public function registerClass(string $class): void { if (is_subclass_of($class, MethodVisibilityProviderInterface::class, true)) { - $callable = Closure::fromCallable([$class, 'isMethodVisible']); + $callable = $class::isMethodVisible(...); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); diff --git a/src/Psalm/Internal/Provider/PropertyExistenceProvider.php b/src/Psalm/Internal/Provider/PropertyExistenceProvider.php index d10e6f2479d..9f6e7b1a5e9 100644 --- a/src/Psalm/Internal/Provider/PropertyExistenceProvider.php +++ b/src/Psalm/Internal/Provider/PropertyExistenceProvider.php @@ -39,7 +39,7 @@ public function __construct() public function registerClass(string $class): void { if (is_subclass_of($class, PropertyExistenceProviderInterface::class, true)) { - $callable = Closure::fromCallable([$class, 'doesPropertyExist']); + $callable = $class::doesPropertyExist(...); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); diff --git a/src/Psalm/Internal/Provider/PropertyTypeProvider.php b/src/Psalm/Internal/Provider/PropertyTypeProvider.php index 71b9231a7f9..19687569af1 100644 --- a/src/Psalm/Internal/Provider/PropertyTypeProvider.php +++ b/src/Psalm/Internal/Provider/PropertyTypeProvider.php @@ -41,7 +41,7 @@ public function __construct() public function registerClass(string $class): void { if (is_subclass_of($class, PropertyTypeProviderInterface::class, true)) { - $callable = Closure::fromCallable([$class, 'getPropertyType']); + $callable = $class::getPropertyType(...); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); From dd8ee0fc30cbbbbccc85de8ed76f50e05cf9fe76 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 20 Oct 2023 11:41:46 +0200 Subject: [PATCH 21/63] Remove legacy code --- .../Internal/Analyzer/ProjectAnalyzer.php | 31 +++---------------- .../Analyzer/Statements/Block/TryAnalyzer.php | 6 +--- src/Psalm/Internal/Cli/Psalm.php | 24 -------------- src/Psalm/Internal/Codebase/Analyzer.php | 1 - src/Psalm/Internal/Codebase/Scanner.php | 1 - src/Psalm/Internal/Fork/Pool.php | 19 ------------ 6 files changed, 6 insertions(+), 76 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index ef9e130aad7..fe12ae02391 100644 --- a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -74,7 +74,6 @@ use function fwrite; use function implode; use function in_array; -use function ini_get; use function is_dir; use function is_file; use function microtime; @@ -90,11 +89,8 @@ use function strtolower; use function substr; use function usort; -use function version_compare; use const PHP_EOL; -use const PHP_OS; -use const PHP_VERSION; use const PSALM_VERSION; use const STDERR; @@ -382,21 +378,13 @@ public function serverMode(LanguageServer $server): void $this->file_reference_provider->loadReferenceCache(); $this->codebase->enterServerMode(); - if (ini_get('pcre.jit') === '1' - && PHP_OS === 'Darwin' - && version_compare(PHP_VERSION, '7.3.0') >= 0 - && version_compare(PHP_VERSION, '7.4.0') < 0 - ) { - // do nothing - } else { - $cpu_count = self::getCpuCount(); + $cpu_count = self::getCpuCount(); - // let's not go crazy - $usable_cpus = $cpu_count - 2; + // let's not go crazy + $usable_cpus = $cpu_count - 2; - if ($usable_cpus > 1) { - $this->threads = $usable_cpus; - } + if ($usable_cpus > 1) { + $this->threads = $usable_cpus; } $server->logInfo("Initializing: Initialize Plugins..."); @@ -1347,15 +1335,6 @@ public static function getCpuCount(): int return 1; } - // PHP 7.3 with JIT on OSX is screwed for multi-threads - if (ini_get('pcre.jit') === '1' - && PHP_OS === 'Darwin' - && version_compare(PHP_VERSION, '7.3.0') >= 0 - && version_compare(PHP_VERSION, '7.4.0') < 0 - ) { - return 1; - } - if (!extension_loaded('pcntl')) { // Psalm requires pcntl for multi-threads support return 1; diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php index 9222f3109a7..2f88ac31e75 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php @@ -27,9 +27,6 @@ use function in_array; use function is_string; use function strtolower; -use function version_compare; - -use const PHP_VERSION; /** * @internal @@ -269,8 +266,7 @@ public static function analyze( $fq_catch_class, false, false, - version_compare(PHP_VERSION, '7.0.0dev', '>=') - && strtolower($fq_catch_class) !== 'throwable' + strtolower($fq_catch_class) !== 'throwable' && $codebase->interfaceExists($fq_catch_class) && !$codebase->interfaceExtends($fq_catch_class, 'Throwable') ? ['Throwable' => new TNamedObject('Throwable')] diff --git a/src/Psalm/Internal/Cli/Psalm.php b/src/Psalm/Internal/Cli/Psalm.php index 5aee0ced16d..8ca086c47fd 100644 --- a/src/Psalm/Internal/Cli/Psalm.php +++ b/src/Psalm/Internal/Cli/Psalm.php @@ -15,7 +15,6 @@ use Psalm\Internal\Codebase\ReferenceMapGenerator; use Psalm\Internal\Composer; use Psalm\Internal\ErrorHandler; -use Psalm\Internal\Fork\Pool; use Psalm\Internal\Fork\PsalmRestarter; use Psalm\Internal\IncludeCollector; use Psalm\Internal\Provider\ClassLikeStorageCacheProvider; @@ -74,15 +73,12 @@ use function str_starts_with; use function strlen; use function substr; -use function version_compare; use const DIRECTORY_SEPARATOR; use const JSON_THROW_ON_ERROR; use const LC_CTYPE; use const PHP_EOL; -use const PHP_OS; use const PHP_URL_SCHEME; -use const PHP_VERSION; use const STDERR; // phpcs:disable PSR1.Files.SideEffects @@ -270,8 +266,6 @@ public static function run(array $argv): void $progress = self::initProgress($options, $config); - self::emitMacPcreWarning($options, $threads); - self::restart($options, $threads, $progress); if (isset($options['debug-emitted-issues'])) { @@ -864,24 +858,6 @@ private static function getCurrentDir(array $options): string return $current_dir; } - private static function emitMacPcreWarning(array $options, int $threads): void - { - if (!isset($options['threads']) - && !isset($options['debug']) - && $threads === 1 - && ini_get('pcre.jit') === '1' - && PHP_OS === 'Darwin' - && version_compare(PHP_VERSION, '7.3.0') >= 0 - && version_compare(PHP_VERSION, '7.4.0') < 0 - ) { - echo( - 'If you want to run Psalm as a language server, or run Psalm with' . PHP_EOL - . 'multiple processes (--threads=4), beware:' . PHP_EOL - . Pool::MAC_PCRE_MESSAGE . PHP_EOL . PHP_EOL - ); - } - } - private static function restart(array $options, int $threads, Progress $progress): void { $ini_handler = new PsalmRestarter('PSALM'); diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php index 843316f12e9..a725158a6a9 100644 --- a/src/Psalm/Internal/Codebase/Analyzer.php +++ b/src/Psalm/Internal/Codebase/Analyzer.php @@ -4,7 +4,6 @@ namespace Psalm\Internal\Codebase; -use Closure; use InvalidArgumentException; use PhpParser; use Psalm\CodeLocation; diff --git a/src/Psalm/Internal/Codebase/Scanner.php b/src/Psalm/Internal/Codebase/Scanner.php index 58269f66544..17740d9f9a7 100644 --- a/src/Psalm/Internal/Codebase/Scanner.php +++ b/src/Psalm/Internal/Codebase/Scanner.php @@ -4,7 +4,6 @@ namespace Psalm\Internal\Codebase; -use Closure; use Psalm\Codebase; use Psalm\Config; use Psalm\Internal\Analyzer\IssueData; diff --git a/src/Psalm/Internal/Fork/Pool.php b/src/Psalm/Internal/Fork/Pool.php index 092956ed463..64fc2ade52f 100644 --- a/src/Psalm/Internal/Fork/Pool.php +++ b/src/Psalm/Internal/Fork/Pool.php @@ -49,11 +49,8 @@ use function substr; use function unserialize; use function usleep; -use function version_compare; use const PHP_EOL; -use const PHP_OS; -use const PHP_VERSION; use const SIGALRM; use const SIGTERM; use const STREAM_IPPROTO_IP; @@ -84,12 +81,6 @@ final class Pool private bool $did_have_error = false; - public const MAC_PCRE_MESSAGE = 'Mac users: pcre.jit is set to 1 in your PHP config.' . PHP_EOL - . 'The pcre jit is known to cause segfaults in PHP 7.3 on Macs, and Psalm' . PHP_EOL - . 'will not execute in threaded mode to avoid indecipherable errors.' . PHP_EOL - . 'Consider adding pcre.jit=0 to your PHP config, or upgrade to PHP 7.4.' . PHP_EOL - . 'Relevant info: https://bugs.php.net/bug.php?id=77260'; - /** * @param array> $process_task_data_iterator * An array of task data items to be divided up among the @@ -135,16 +126,6 @@ public function __construct( exit(1); } - if (ini_get('pcre.jit') === '1' - && PHP_OS === 'Darwin' - && version_compare(PHP_VERSION, '7.3.0') >= 0 - && version_compare(PHP_VERSION, '7.4.0') < 0 - ) { - die( - self::MAC_PCRE_MESSAGE . PHP_EOL - ); - } - // We'll keep track of if this is the parent process // so that we can tell who will be doing the waiting $is_parent = false; From 97e5a077e72bdcc9453f8e0aa771acf5b59c8aae Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 13:47:26 +0200 Subject: [PATCH 22/63] Switch back to function JIT --- composer.json | 1 - src/Psalm/Internal/Fork/PsalmRestarter.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 666260b66da..0a36e057c1f 100644 --- a/composer.json +++ b/composer.json @@ -58,7 +58,6 @@ "phpunit/phpunit": "^9.6", "psalm/plugin-mockery": "^1.1", "psalm/plugin-phpunit": "^0.18", - "rector/rector": "^0.18.5", "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.6", "symfony/process": "^4.4 || ^5.0 || ^6.0" diff --git a/src/Psalm/Internal/Fork/PsalmRestarter.php b/src/Psalm/Internal/Fork/PsalmRestarter.php index 30f8e234d44..d74e5424e94 100644 --- a/src/Psalm/Internal/Fork/PsalmRestarter.php +++ b/src/Psalm/Internal/Fork/PsalmRestarter.php @@ -28,7 +28,7 @@ final class PsalmRestarter extends XdebugHandler { private const REQUIRED_OPCACHE_SETTINGS = [ 'enable_cli' => 1, - 'jit' => 1254, + 'jit' => 1205, 'validate_timestamps' => 0, 'file_update_protection' => 0, 'jit_buffer_size' => 512 * 1024 * 1024, @@ -88,7 +88,7 @@ protected function requiresRestart($default): bool if ($ini_name === 'jit_buffer_size') { $value = self::toBytes($value); } elseif ($ini_name === 'enable_cli') { - $value = in_array($value, ['1', 'true', true, 1]); + $value = in_array($value, ['1', 'true', true, 1]) ? 1 : 0; } elseif (is_int($required_value)) { $required_value = (int) $required_value; } From e3396aa61d3d3d46b0dc9ae9030d82af329d8f48 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 14:17:17 +0200 Subject: [PATCH 23/63] Fixes --- .../Internal/Analyzer/NamespaceAnalyzer.php | 1 - .../Statements/Expression/AssertionFinder.php | 44 ++++++++++--------- src/Psalm/Internal/Fork/PsalmRestarter.php | 2 +- .../LanguageServer/Client/Workspace.php | 5 --- src/Psalm/Internal/Scanner/FileScanner.php | 2 +- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php index fb1e9f896e6..6abd248d7b7 100644 --- a/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php @@ -41,7 +41,6 @@ public function __construct( private readonly Namespace_ $namespace, /** * @var FileAnalyzer - * @psalm-suppress NonInvariantDocblockPropertyType */ protected SourceAnalyzer $source, ) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php index 9afa824beb6..556b8251020 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php @@ -1465,7 +1465,7 @@ private static function hasGetClassCheck( && strtolower($conditional->right->name->name) === 'class'; $right_variable_class_const = $conditional->right instanceof PhpParser\Node\Expr\ClassConstFetch - && $conditional->right->class instanceof PhpParser\Node\Expr\Variable + && !$conditional->right->class instanceof PhpParser\Node\Name && $conditional->right->name instanceof PhpParser\Node\Identifier && strtolower($conditional->right->name->name) === 'class'; @@ -1474,15 +1474,22 @@ private static function hasGetClassCheck( && $conditional->left->name instanceof PhpParser\Node\Identifier && strtolower($conditional->left->name->name) === 'class'; - $left_type = $source->node_data->getType($conditional->left); + $left_variable_class_const = $conditional->left instanceof PhpParser\Node\Expr\ClassConstFetch + && !$conditional->left->class instanceof PhpParser\Node\Name + && $conditional->left->name instanceof PhpParser\Node\Identifier + && strtolower($conditional->left->name->name) === 'class'; $left_class_string_t = false; - if ($left_type && $left_type->isSingle()) { - foreach ($left_type->getAtomicTypes() as $type_part) { - if ($type_part instanceof TClassString) { - $left_class_string_t = true; - break; + if (!$left_variable_class_const) { + $left_type = $source->node_data->getType($conditional->left); + + if ($left_type && $left_type->isSingle()) { + foreach ($left_type->getAtomicTypes() as $type_part) { + if ($type_part instanceof TClassString) { + $left_class_string_t = true; + break; + } } } } @@ -1503,29 +1510,26 @@ private static function hasGetClassCheck( && $conditional->left->name instanceof PhpParser\Node\Identifier && strtolower($conditional->left->name->name) === 'class'; - $left_variable_class_const = $conditional->left instanceof PhpParser\Node\Expr\ClassConstFetch - && $conditional->left->class instanceof PhpParser\Node\Expr\Variable - && $conditional->left->name instanceof PhpParser\Node\Identifier - && strtolower($conditional->left->name->name) === 'class'; - $right_class_string = $conditional->right instanceof PhpParser\Node\Expr\ClassConstFetch && $conditional->right->class instanceof PhpParser\Node\Name && $conditional->right->name instanceof PhpParser\Node\Identifier && strtolower($conditional->right->name->name) === 'class'; - $right_type = $source->node_data->getType($conditional->right); - $right_class_string_t = false; - if ($right_type && $right_type->isSingle()) { - foreach ($right_type->getAtomicTypes() as $type_part) { - if ($type_part instanceof TClassString) { - $right_class_string_t = true; - break; + if (!$right_variable_class_const) { + $right_type = $source->node_data->getType($conditional->right); + + if ($right_type && $right_type->isSingle()) { + foreach ($right_type->getAtomicTypes() as $type_part) { + if ($type_part instanceof TClassString) { + $right_class_string_t = true; + break; + } } } } - + if (($left_get_class || $left_static_class || $left_variable_class_const) && ($right_class_string || $right_class_string_t) ) { diff --git a/src/Psalm/Internal/Fork/PsalmRestarter.php b/src/Psalm/Internal/Fork/PsalmRestarter.php index d74e5424e94..d024145139d 100644 --- a/src/Psalm/Internal/Fork/PsalmRestarter.php +++ b/src/Psalm/Internal/Fork/PsalmRestarter.php @@ -90,7 +90,7 @@ protected function requiresRestart($default): bool } elseif ($ini_name === 'enable_cli') { $value = in_array($value, ['1', 'true', true, 1]) ? 1 : 0; } elseif (is_int($required_value)) { - $required_value = (int) $required_value; + $value = (int) $value; } if ($value !== $required_value) { return true; diff --git a/src/Psalm/Internal/LanguageServer/Client/Workspace.php b/src/Psalm/Internal/LanguageServer/Client/Workspace.php index eedb9431548..164a3b83e67 100644 --- a/src/Psalm/Internal/LanguageServer/Client/Workspace.php +++ b/src/Psalm/Internal/LanguageServer/Client/Workspace.php @@ -4,7 +4,6 @@ namespace Psalm\Internal\LanguageServer\Client; -use JsonMapper; use Psalm\Internal\LanguageServer\ClientHandler; use Psalm\Internal\LanguageServer\LanguageServer; @@ -17,10 +16,6 @@ final class Workspace { public function __construct( private readonly ClientHandler $handler, - /** - * @psalm-suppress UnusedProperty - */ - private readonly JsonMapper $mapper, private readonly LanguageServer $server, ) { } diff --git a/src/Psalm/Internal/Scanner/FileScanner.php b/src/Psalm/Internal/Scanner/FileScanner.php index d7bf827fecb..d8ba100c47f 100644 --- a/src/Psalm/Internal/Scanner/FileScanner.php +++ b/src/Psalm/Internal/Scanner/FileScanner.php @@ -18,7 +18,7 @@ * @internal * @psalm-consistent-constructor */ -final class FileScanner implements FileSource +class FileScanner implements FileSource { public function __construct(public string $file_path, public string $file_name, public bool $will_analyze) { From e19caf0a165431ff5e4cdeaf3815248326ef9e4f Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 14:20:08 +0200 Subject: [PATCH 24/63] Fix --- psalm-baseline.xml | 35 +++++++++++++++++-- .../LanguageServer/LanguageClient.php | 2 +- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index d04ba234885..addca310623 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + tags['variablesfrom'][0]]]> @@ -16,6 +16,9 @@ $deprecated_element_xml + + $this + @@ -42,6 +45,11 @@ $property_name + + + $source + + $destination_parts[1] @@ -302,6 +310,11 @@ $buffer + + + $findUnusedVariables + + $config @@ -353,7 +366,15 @@ - + + $line_parts + + + , string>]]> + + + $line_parts[0] + $line_parts[1] $since_parts[1] @@ -622,6 +643,16 @@ hasLowercaseString + + + Config + + + public function __construct() + public function getComposerFilePathForClassLike(string $fq_classlike_name): bool + public function getProjectDirectories(): array + + diff --git a/src/Psalm/Internal/LanguageServer/LanguageClient.php b/src/Psalm/Internal/LanguageServer/LanguageClient.php index a355c6d9da8..19131ca5c2e 100644 --- a/src/Psalm/Internal/LanguageServer/LanguageClient.php +++ b/src/Psalm/Internal/LanguageServer/LanguageClient.php @@ -56,7 +56,7 @@ public function __construct( $this->handler = new ClientHandler($reader, $writer); $this->textDocument = new ClientTextDocument($this->handler, $this->server); - $this->workspace = new ClientWorkspace($this->handler, new JsonMapper, $this->server); + $this->workspace = new ClientWorkspace($this->handler, $this->server); } /** From 8ff340e588a1c9513bdd3c706f797fd7737df12f Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 14:28:58 +0200 Subject: [PATCH 25/63] Fixup --- src/Psalm/Aliases.php | 11 +++- src/Psalm/Config/Creator.php | 6 +- .../Internal/Analyzer/ClassLikeAnalyzer.php | 2 +- .../Analyzer/ClassLikeNameOptions.php | 10 +++- .../Internal/Analyzer/DataFlowNodeData.php | 15 ++++- src/Psalm/Internal/Analyzer/FileAnalyzer.php | 7 ++- .../Analyzer/FunctionLikeAnalyzer.php | 7 ++- src/Psalm/Internal/Analyzer/IssueData.php | 55 ++++--------------- .../Internal/Diff/ClassStatementsDiffer.php | 2 - .../LanguageServer/LanguageClient.php | 1 - src/Psalm/Issue/CodeIssue.php | 10 +--- src/Psalm/Issue/TaintedInput.php | 10 +--- src/Psalm/Storage/Assertion/NotInArray.php | 5 +- tests/EnumTest.php | 2 +- 14 files changed, 63 insertions(+), 80 deletions(-) diff --git a/src/Psalm/Aliases.php b/src/Psalm/Aliases.php index 2dedcf01c1f..ea49c47f530 100644 --- a/src/Psalm/Aliases.php +++ b/src/Psalm/Aliases.php @@ -22,7 +22,14 @@ final class Aliases * @internal * @psalm-mutation-free */ - public function __construct(public ?string $namespace = null, public array $uses = [], public array $functions = [], public array $constants = [], public array $uses_flipped = [], public array $functions_flipped = [], public array $constants_flipped = []) - { + public function __construct( + public ?string $namespace = null, + public array $uses = [], + public array $functions = [], + public array $constants = [], + public array $uses_flipped = [], + public array $functions_flipped = [], + public array $constants_flipped = [], + ) { } } diff --git a/src/Psalm/Config/Creator.php b/src/Psalm/Config/Creator.php index e0b2fd532bb..2f88ade1042 100644 --- a/src/Psalm/Config/Creator.php +++ b/src/Psalm/Config/Creator.php @@ -289,7 +289,11 @@ private static function guessPhpFileDirs(string $current_dir): array $nodes = []; /** @var string[] */ - $php_files = [...glob($current_dir . DIRECTORY_SEPARATOR . '*.php', GLOB_NOSORT) ?: [], ...glob($current_dir . DIRECTORY_SEPARATOR . '**/*.php', GLOB_NOSORT) ?: [], ...glob($current_dir . DIRECTORY_SEPARATOR . '**/**/*.php', GLOB_NOSORT) ?: []]; + $php_files = [ + ...glob($current_dir . DIRECTORY_SEPARATOR . '*.php', GLOB_NOSORT) ?: [], + ...glob($current_dir . DIRECTORY_SEPARATOR . '**/*.php', GLOB_NOSORT) ?: [], + ...glob($current_dir . DIRECTORY_SEPARATOR . '**/**/*.php', GLOB_NOSORT) ?: [], + ]; foreach ($php_files as $php_file) { $php_file = str_replace($current_dir . DIRECTORY_SEPARATOR, '', $php_file); diff --git a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php index 707e3af12e1..83adbb7da94 100644 --- a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php @@ -200,7 +200,7 @@ public static function checkFullyQualifiedClassLikeName( ?string $calling_method_id, array $suppressed_issues, ?ClassLikeNameOptions $options = null, - bool $check_classes = true + bool $check_classes = true, ): ?bool { if ($options === null) { $options = new ClassLikeNameOptions(); diff --git a/src/Psalm/Internal/Analyzer/ClassLikeNameOptions.php b/src/Psalm/Internal/Analyzer/ClassLikeNameOptions.php index 4c91c6b920b..64e9db31885 100644 --- a/src/Psalm/Internal/Analyzer/ClassLikeNameOptions.php +++ b/src/Psalm/Internal/Analyzer/ClassLikeNameOptions.php @@ -9,7 +9,13 @@ */ final class ClassLikeNameOptions { - public function __construct(public bool $inferred = false, public bool $allow_trait = false, public bool $allow_interface = true, public bool $allow_enum = true, public bool $from_docblock = false, public bool $from_attribute = false) - { + public function __construct( + public bool $inferred = false, + public bool $allow_trait = false, + public bool $allow_interface = true, + public bool $allow_enum = true, + public bool $from_docblock = false, + public bool $from_attribute = false, + ) { } } diff --git a/src/Psalm/Internal/Analyzer/DataFlowNodeData.php b/src/Psalm/Internal/Analyzer/DataFlowNodeData.php index da99e343596..4e13c5b0a7f 100644 --- a/src/Psalm/Internal/Analyzer/DataFlowNodeData.php +++ b/src/Psalm/Internal/Analyzer/DataFlowNodeData.php @@ -14,7 +14,18 @@ final class DataFlowNodeData { use ImmutableNonCloneableTrait; - public function __construct(public string $label, public int $line_from, public int $line_to, public string $file_name, public string $file_path, public string $snippet, public int $from, public int $to, public int $snippet_from, public int $column_from, public int $column_to) - { + public function __construct( + public string $label, + public int $line_from, + public int $line_to, + public string $file_name, + public string $file_path, + public string $snippet, + public int $from, + public int $to, + public int $snippet_from, + public int $column_from, + public int $column_to, + ) { } } diff --git a/src/Psalm/Internal/Analyzer/FileAnalyzer.php b/src/Psalm/Internal/Analyzer/FileAnalyzer.php index f18593633ae..bbbe7c41c1e 100644 --- a/src/Psalm/Internal/Analyzer/FileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FileAnalyzer.php @@ -99,8 +99,11 @@ class FileAnalyzer extends SourceAnalyzer private ?Union $return_type = null; - public function __construct(public ProjectAnalyzer $project_analyzer, protected string $file_path, protected string $file_name) - { + public function __construct( + public ProjectAnalyzer $project_analyzer, + protected string $file_path, + protected string $file_name, + ) { $this->source = $this; $this->codebase = $project_analyzer->getCodebase(); } diff --git a/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php b/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php index 0573629c6cb..217d7c5ebe0 100644 --- a/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php @@ -134,8 +134,11 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer /** * @param TFunction $function */ - public function __construct(protected Closure|Function_|ClassMethod|ArrowFunction $function, SourceAnalyzer $source, protected FunctionLikeStorage $storage) - { + public function __construct( + protected Closure|Function_|ClassMethod|ArrowFunction $function, + SourceAnalyzer $source, + protected FunctionLikeStorage $storage, + ) { $this->source = $source; $this->suppressed_issues = $source->getSuppressedIssues(); $this->codebase = $source->getCodebase(); diff --git a/src/Psalm/Internal/Analyzer/IssueData.php b/src/Psalm/Internal/Analyzer/IssueData.php index c8674fd8fa4..e948337ce45 100644 --- a/src/Psalm/Internal/Analyzer/IssueData.php +++ b/src/Psalm/Internal/Analyzer/IssueData.php @@ -16,10 +16,7 @@ final class IssueData public const SEVERITY_INFO = 'info'; public const SEVERITY_ERROR = 'error'; - /** - * @readonly - */ - public string $link; + public readonly string $link; /** * @param self::SEVERITY_* $severity @@ -30,53 +27,23 @@ public function __construct( public string $severity, public int $line_from, public int $line_to, - /** - * @readonly - */ - public string $type, - /** - * @readonly - */ - public string $message, - /** - * @readonly - */ - public string $file_name, - /** - * @readonly - */ - public string $file_path, - /** - * @readonly - */ - public string $snippet, - /** - * @readonly - */ - public string $selected_text, + public readonly string $type, + public readonly string $message, + public readonly string $file_name, + public readonly string $file_path, + public readonly string $snippet, + public readonly string $selected_text, public int $from, public int $to, public int $snippet_from, public int $snippet_to, - /** - * @readonly - */ - public int $column_from, - /** - * @readonly - */ - public int $column_to, - /** - * @readonly - */ - public int $shortcode = 0, + public readonly int $column_from, + public readonly int $column_to, + public readonly int $shortcode = 0, public int $error_level = -1, public ?array $taint_trace = null, public ?array $other_references = null, - /** - * @readonly - */ - public ?string $dupe_key = null, + public readonly ?string $dupe_key = null, ) { $this->link = $shortcode ? 'https://psalm.dev/' . str_pad((string) $shortcode, 3, "0", STR_PAD_LEFT) : ''; } diff --git a/src/Psalm/Internal/Diff/ClassStatementsDiffer.php b/src/Psalm/Internal/Diff/ClassStatementsDiffer.php index 91e65091e47..95f702e9834 100644 --- a/src/Psalm/Internal/Diff/ClassStatementsDiffer.php +++ b/src/Psalm/Internal/Diff/ClassStatementsDiffer.php @@ -8,9 +8,7 @@ use UnexpectedValueException; use function count; -use function get_class; use function is_string; -use function strpos; use function str_contains; use function strtolower; use function substr; diff --git a/src/Psalm/Internal/LanguageServer/LanguageClient.php b/src/Psalm/Internal/LanguageServer/LanguageClient.php index 19131ca5c2e..12cdfc86c8b 100644 --- a/src/Psalm/Internal/LanguageServer/LanguageClient.php +++ b/src/Psalm/Internal/LanguageServer/LanguageClient.php @@ -4,7 +4,6 @@ namespace Psalm\Internal\LanguageServer; -use JsonMapper; use LanguageServerProtocol\LogMessage; use LanguageServerProtocol\LogTrace; use Psalm\Internal\LanguageServer\Client\Progress\LegacyProgress; diff --git a/src/Psalm/Issue/CodeIssue.php b/src/Psalm/Issue/CodeIssue.php index a5127b3cfef..5a321fd1d9e 100644 --- a/src/Psalm/Issue/CodeIssue.php +++ b/src/Psalm/Issue/CodeIssue.php @@ -20,14 +20,8 @@ abstract class CodeIssue public ?string $dupe_key = null; public function __construct( - /** - * @readonly - */ - public string $message, - /** - * @readonly - */ - public CodeLocation $code_location, + public readonly string $message, + public readonly CodeLocation $code_location, ) { } diff --git a/src/Psalm/Issue/TaintedInput.php b/src/Psalm/Issue/TaintedInput.php index b09361eab05..61d54370ad5 100644 --- a/src/Psalm/Issue/TaintedInput.php +++ b/src/Psalm/Issue/TaintedInput.php @@ -19,14 +19,8 @@ abstract class TaintedInput extends CodeIssue public function __construct( string $message, CodeLocation $code_location, - /** - * @readonly - */ - public array $journey, - /** - * @readonly - */ - public string $journey_text, + public readonly array $journey, + public readonly string $journey_text, ) { parent::__construct($message, $code_location); } diff --git a/src/Psalm/Storage/Assertion/NotInArray.php b/src/Psalm/Storage/Assertion/NotInArray.php index af24e98de59..17c385f8825 100644 --- a/src/Psalm/Storage/Assertion/NotInArray.php +++ b/src/Psalm/Storage/Assertion/NotInArray.php @@ -13,10 +13,7 @@ final class NotInArray extends Assertion { public function __construct( - /** - * @readonly - */ - public Union $type, + public readonly Union $type, ) { } diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 6f128dc2d32..35df957b6b3 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -632,7 +632,7 @@ function noop(string $s): string $foo = FooEnum::Foo->value; noop($foo); noop(FooEnum::Foo->value); - PHP + PHP, ], 'backedEnumCaseValueFromClassConstant' => [ 'code' => <<<'PHP' From b709673241b53f0b2745603f08ad9fe385550690 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 14:30:43 +0200 Subject: [PATCH 26/63] Fixes --- src/Psalm/Issue/MixedArgument.php | 3 +-- src/Psalm/Issue/MixedArgumentTypeCoercion.php | 3 +-- src/Psalm/Issue/MixedIssueTrait.php | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Psalm/Issue/MixedArgument.php b/src/Psalm/Issue/MixedArgument.php index dde5c5af001..12f50357a33 100644 --- a/src/Psalm/Issue/MixedArgument.php +++ b/src/Psalm/Issue/MixedArgument.php @@ -21,8 +21,7 @@ public function __construct( ?string $function_id = null, ?CodeLocation $origin_location = null, ) { - $this->code_location = $code_location; - $this->message = $message; + parent::__construct($message, $code_location); $this->function_id = $function_id ? strtolower($function_id) : null; $this->origin_location = $origin_location; } diff --git a/src/Psalm/Issue/MixedArgumentTypeCoercion.php b/src/Psalm/Issue/MixedArgumentTypeCoercion.php index a7bd8f43d92..078a4e916b2 100644 --- a/src/Psalm/Issue/MixedArgumentTypeCoercion.php +++ b/src/Psalm/Issue/MixedArgumentTypeCoercion.php @@ -21,8 +21,7 @@ public function __construct( ?string $function_id = null, ?CodeLocation $origin_location = null, ) { - $this->code_location = $code_location; - $this->message = $message; + parent::__construct($message, $code_location); $this->function_id = $function_id ? strtolower($function_id) : null; $this->origin_location = $origin_location; } diff --git a/src/Psalm/Issue/MixedIssueTrait.php b/src/Psalm/Issue/MixedIssueTrait.php index 10dda63d98a..31f371de6f2 100644 --- a/src/Psalm/Issue/MixedIssueTrait.php +++ b/src/Psalm/Issue/MixedIssueTrait.php @@ -18,8 +18,7 @@ public function __construct( CodeLocation $code_location, ?CodeLocation $origin_location = null, ) { - $this->code_location = $code_location; - $this->message = $message; + parent::__construct($message, $code_location); $this->origin_location = $origin_location; } From d0f832f5f6e2e41197159675c9fc253a70966d71 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 14:38:38 +0200 Subject: [PATCH 27/63] cs-fixes --- .../Expression/BinaryOp/OrAnalyzer.php | 20 +++- .../Call/ArrayFunctionArgumentsAnalyzer.php | 7 +- src/Psalm/Internal/Codebase/Populator.php | 40 ++++++-- src/Psalm/Internal/Fork/PsalmRestarter.php | 8 +- src/Psalm/IssueBuffer.php | 96 +++++++++++++++---- 5 files changed, 137 insertions(+), 34 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php index 886dadbf075..d43c33936bd 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php @@ -354,7 +354,10 @@ public static function analyze( $context->updateChecks($right_context); } - $context->cond_referenced_var_ids = [...$right_context->cond_referenced_var_ids, ...$context->cond_referenced_var_ids]; + $context->cond_referenced_var_ids = [ + ...$right_context->cond_referenced_var_ids, + ...$context->cond_referenced_var_ids, + ]; $context->assigned_var_ids = [...$context->assigned_var_ids, ...$right_context->assigned_var_ids]; @@ -377,14 +380,23 @@ public static function analyze( } } - $if_body_context->cond_referenced_var_ids = [...$context->cond_referenced_var_ids, ...$if_body_context->cond_referenced_var_ids]; + $if_body_context->cond_referenced_var_ids = [ + ...$context->cond_referenced_var_ids, + ...$if_body_context->cond_referenced_var_ids, + ]; - $if_body_context->assigned_var_ids = [...$context->assigned_var_ids, ...$if_body_context->assigned_var_ids]; + $if_body_context->assigned_var_ids = [ + ...$context->assigned_var_ids, + ...$if_body_context->assigned_var_ids, + ]; $if_body_context->updateChecks($context); } - $context->vars_possibly_in_scope = [...$right_context->vars_possibly_in_scope, ...$context->vars_possibly_in_scope]; + $context->vars_possibly_in_scope = [ + ...$right_context->vars_possibly_in_scope, + ...$context->vars_possibly_in_scope, + ]; return true; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php index e011b84fc82..a8465bf5656 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php @@ -459,8 +459,11 @@ public static function handleSplice( $length_min = (int) $length_literal->value; } } else { - $literals = [...$length_arg_type->getLiteralStrings(), ...$length_arg_type->getLiteralInts(), ...$length_arg_type->getLiteralFloats()]; - foreach ($literals as $literal) { + foreach ([ + ...$length_arg_type->getLiteralStrings(), + ...$length_arg_type->getLiteralInts(), + ...$length_arg_type->getLiteralFloats(), + ] as $literal) { if ($literal->isNumericType() && ($literal_val = (int) $literal->value) && ((isset($length_min) && $length_min> $literal_val) || !isset($length_min))) { diff --git a/src/Psalm/Internal/Codebase/Populator.php b/src/Psalm/Internal/Codebase/Populator.php index 15b790e9643..c0753196f49 100644 --- a/src/Psalm/Internal/Codebase/Populator.php +++ b/src/Psalm/Internal/Codebase/Populator.php @@ -560,7 +560,10 @@ private function populateInterfaceData( => $constant->visibility === ClassLikeAnalyzer::VISIBILITY_PUBLIC, ), ...$storage->constants]; - $storage->invalid_dependencies = [...$storage->invalid_dependencies, ...$interface_storage->invalid_dependencies]; + $storage->invalid_dependencies = [ + ...$storage->invalid_dependencies, + ...$interface_storage->invalid_dependencies, + ]; self::extendTemplateParams($storage, $interface_storage, false); @@ -711,7 +714,10 @@ private function populateDataFromImplementedInterface( $dependent_classlikes, ); - $storage->class_implements = [...$storage->class_implements, ...$implemented_interface_storage->parent_interfaces]; + $storage->class_implements = [ + ...$storage->class_implements, + ...$implemented_interface_storage->parent_interfaces, + ]; } /** @@ -752,9 +758,15 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file continue; } - $storage->declaring_function_ids = [...$included_file_storage->declaring_function_ids, ...$storage->declaring_function_ids]; + $storage->declaring_function_ids = [ + ...$included_file_storage->declaring_function_ids, + ...$storage->declaring_function_ids, + ]; - $storage->declaring_constants = [...$included_file_storage->declaring_constants, ...$storage->declaring_constants]; + $storage->declaring_constants = [ + ...$included_file_storage->declaring_constants, + ...$storage->declaring_constants, + ]; } foreach ($storage->referenced_classlikes as $fq_class_name) { @@ -793,10 +805,16 @@ private function populateFileStorage(FileStorage $storage, array $dependent_file continue; } - $storage->declaring_function_ids = [...$included_trait_file_storage->declaring_function_ids, ...$storage->declaring_function_ids]; + $storage->declaring_function_ids = [ + ...$included_trait_file_storage->declaring_function_ids, + ...$storage->declaring_function_ids, + ]; } - $storage->declaring_function_ids = [...$included_file_storage->declaring_function_ids, ...$storage->declaring_function_ids]; + $storage->declaring_function_ids = [ + ...$included_file_storage->declaring_function_ids, + ...$storage->declaring_function_ids, + ]; } $storage->required_file_paths = $all_required_file_paths; @@ -888,7 +906,10 @@ private function inheritMethodsFromParent( if ($parent_storage->is_trait && $storage->trait_alias_map ) { - $aliased_method_names = [...$aliased_method_names, ...array_keys($storage->trait_alias_map, $method_name_lc, true)]; + $aliased_method_names = [ + ...$aliased_method_names, + ...array_keys($storage->trait_alias_map, $method_name_lc, true), + ]; } foreach ($aliased_method_names as $aliased_method_name) { @@ -955,7 +976,10 @@ private function inheritMethodsFromParent( if ($parent_storage->is_trait && $storage->trait_alias_map ) { - $aliased_method_names = [...$aliased_method_names, ...array_keys($storage->trait_alias_map, $method_name_lc, true)]; + $aliased_method_names = [ + ...$aliased_method_names, + ...array_keys($storage->trait_alias_map, $method_name_lc, true), + ]; } foreach ($aliased_method_names as $aliased_method_name) { diff --git a/src/Psalm/Internal/Fork/PsalmRestarter.php b/src/Psalm/Internal/Fork/PsalmRestarter.php index d024145139d..9332cdaab75 100644 --- a/src/Psalm/Internal/Fork/PsalmRestarter.php +++ b/src/Psalm/Internal/Fork/PsalmRestarter.php @@ -32,11 +32,11 @@ final class PsalmRestarter extends XdebugHandler 'validate_timestamps' => 0, 'file_update_protection' => 0, 'jit_buffer_size' => 512 * 1024 * 1024, - 'max_accelerated_files' => 1000000, + 'max_accelerated_files' => 1_000_000, 'interned_strings_buffer' => 64, - 'jit_max_root_traces' => 30000000, - 'jit_max_side_traces' => 30000000, - 'jit_max_exit_counters' => 30000000, + 'jit_max_root_traces' => 30_000_000, + 'jit_max_side_traces' => 30_000_000, + 'jit_max_exit_counters' => 30_000_000, 'jit_hot_loop' => 1, 'jit_hot_func' => 1, 'jit_hot_return' => 1, diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index 333197a97ee..0f0eb5e6df2 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -858,11 +858,31 @@ public static function getOutput( $format = $report_options->format; $output = match ($format) { - Report::TYPE_COMPACT => new CompactReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_EMACS => new EmacsReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_TEXT => new TextReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_JSON => new JsonReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_BY_ISSUE_LEVEL => new ByIssueLevelAndTypeReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_COMPACT => new CompactReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_EMACS => new EmacsReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_TEXT => new TextReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_JSON => new JsonReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_BY_ISSUE_LEVEL => new ByIssueLevelAndTypeReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), Report::TYPE_JSON_SUMMARY => new JsonSummaryReport( $normalized_data, self::$fixable_issue_counts, @@ -870,17 +890,61 @@ public static function getOutput( $mixed_expression_count, $total_expression_count, ), - Report::TYPE_SONARQUBE => new SonarqubeReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_PYLINT => new PylintReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_CHECKSTYLE => new CheckstyleReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_XML => new XmlReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_JUNIT => new JunitReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_CONSOLE => new ConsoleReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_GITHUB_ACTIONS => new GithubActionsReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_PHP_STORM => new PhpStormReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_SARIF => new SarifReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_CODECLIMATE => new CodeClimateReport($normalized_data, self::$fixable_issue_counts, $report_options), - Report::TYPE_COUNT => new CountReport($normalized_data, self::$fixable_issue_counts, $report_options), + Report::TYPE_SONARQUBE => new SonarqubeReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_PYLINT => new PylintReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_CHECKSTYLE => new CheckstyleReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_XML => new XmlReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_JUNIT => new JunitReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_CONSOLE => new ConsoleReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_GITHUB_ACTIONS => new GithubActionsReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_PHP_STORM => new PhpStormReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_SARIF => new SarifReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_CODECLIMATE => new CodeClimateReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), + Report::TYPE_COUNT => new CountReport( + $normalized_data, + self::$fixable_issue_counts, + $report_options, + ), }; return $output->create(); From a36d2fcb8414d154fefbd7e5d86ea93c76cf9302 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 14:45:30 +0200 Subject: [PATCH 28/63] cs-fixes --- .../Analyzer/FunctionLikeAnalyzer.php | 10 ++++++++-- .../Analyzer/Statements/Block/DoAnalyzer.php | 5 ++++- .../Statements/Block/ForeachAnalyzer.php | 5 ++++- .../Statements/Block/IfElse/ElseAnalyzer.php | 15 +++++++++++--- .../Block/IfElse/ElseIfAnalyzer.php | 15 +++++++++++--- .../Statements/Block/IfElse/IfAnalyzer.php | 10 ++++++++-- .../Statements/Block/IfElseAnalyzer.php | 12 ++++++++--- .../Statements/Block/LoopAnalyzer.php | 15 +++++++++++--- .../Statements/Block/SwitchAnalyzer.php | 5 ++++- .../Statements/Block/WhileAnalyzer.php | 5 ++++- .../Expression/BinaryOp/AndAnalyzer.php | 20 +++++++++++++++---- .../Expression/BinaryOp/OrAnalyzer.php | 10 ++++++++-- .../Statements/Expression/TernaryAnalyzer.php | 16 ++++++++++++--- 13 files changed, 114 insertions(+), 29 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php b/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php index 217d7c5ebe0..a06bb042383 100644 --- a/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php @@ -799,7 +799,10 @@ public function analyze( } if ($this->return_vars_possibly_in_scope !== null) { - $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$this->return_vars_possibly_in_scope]; + $context->vars_possibly_in_scope = [ + ...$context->vars_possibly_in_scope, + ...$this->return_vars_possibly_in_scope, + ]; } foreach ($context->vars_in_scope as $var => $_) { @@ -1537,7 +1540,10 @@ public function addReturnTypes(Context $context): void } if ($this->return_vars_possibly_in_scope !== null) { - $this->return_vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$this->return_vars_possibly_in_scope]; + $this->return_vars_possibly_in_scope = [ + ...$context->vars_possibly_in_scope, + ...$this->return_vars_possibly_in_scope, + ]; } else { $this->return_vars_possibly_in_scope = $context->vars_possibly_in_scope; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php index d23b31785b2..3fc0b4f3563 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php @@ -157,7 +157,10 @@ static function (Clause $c) use ($mixed_var_ids): bool { $do_context->loop_scope = null; - $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$do_context->vars_possibly_in_scope]; + $context->vars_possibly_in_scope = [ + ...$context->vars_possibly_in_scope, + ...$do_context->vars_possibly_in_scope, + ]; if ($context->collect_exceptions) { $context->mergeExceptions($inner_loop_context); diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php index 5843cb1c3e3..f5e6c26d61d 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php @@ -385,7 +385,10 @@ public static function analyze( $foreach_context->loop_scope = null; - $context->vars_possibly_in_scope = [...$foreach_context->vars_possibly_in_scope, ...$context->vars_possibly_in_scope]; + $context->vars_possibly_in_scope = [ + ...$foreach_context->vars_possibly_in_scope, + ...$context->vars_possibly_in_scope, + ]; if ($context->collect_exceptions) { $context->mergeExceptions($foreach_context); diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php index 538fba9af43..568a19e1a88 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseAnalyzer.php @@ -200,13 +200,22 @@ public static function analyze( if ($has_leaving_statements) { if ($else_context->loop_scope) { if (!$has_continue_statement && !$has_break_statement) { - $if_scope->new_vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; + $if_scope->new_vars_possibly_in_scope = [ + ...$vars_possibly_in_scope, + ...$if_scope->new_vars_possibly_in_scope, + ]; } - $else_context->loop_scope->vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$else_context->loop_scope->vars_possibly_in_scope]; + $else_context->loop_scope->vars_possibly_in_scope = [ + ...$vars_possibly_in_scope, + ...$else_context->loop_scope->vars_possibly_in_scope, + ]; } } else { - $if_scope->new_vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; + $if_scope->new_vars_possibly_in_scope = [ + ...$vars_possibly_in_scope, + ...$if_scope->new_vars_possibly_in_scope, + ]; $if_scope->possibly_assigned_var_ids = array_merge( $possibly_assigned_var_ids, diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php index da72058bf2c..f4aa30a1982 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php @@ -373,16 +373,25 @@ public static function analyze( if ($has_leaving_statements && $elseif_context->loop_scope) { if (!$has_continue_statement && !$has_break_statement) { - $if_scope->new_vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; + $if_scope->new_vars_possibly_in_scope = [ + ...$vars_possibly_in_scope, + ...$if_scope->new_vars_possibly_in_scope, + ]; $if_scope->possibly_assigned_var_ids = array_merge( $possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids, ); } - $elseif_context->loop_scope->vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$elseif_context->loop_scope->vars_possibly_in_scope]; + $elseif_context->loop_scope->vars_possibly_in_scope = [ + ...$vars_possibly_in_scope, + ...$elseif_context->loop_scope->vars_possibly_in_scope, + ]; } elseif (!$has_leaving_statements) { - $if_scope->new_vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; + $if_scope->new_vars_possibly_in_scope = [ + ...$vars_possibly_in_scope, + ...$if_scope->new_vars_possibly_in_scope, + ]; $if_scope->possibly_assigned_var_ids = array_merge( $possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids, diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php index 45cc2598001..f33c93d86f0 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php @@ -146,7 +146,10 @@ public static function analyze( $if_context->reconciled_expression_clauses = []; - $outer_context->vars_possibly_in_scope = [...$if_context->vars_possibly_in_scope, ...$outer_context->vars_possibly_in_scope]; + $outer_context->vars_possibly_in_scope = [ + ...$if_context->vars_possibly_in_scope, + ...$outer_context->vars_possibly_in_scope, + ]; $old_if_context = clone $if_context; @@ -305,7 +308,10 @@ public static function analyze( $if_scope->new_vars_possibly_in_scope = $vars_possibly_in_scope; } - $if_context->loop_scope->vars_possibly_in_scope = [...$vars_possibly_in_scope, ...$if_context->loop_scope->vars_possibly_in_scope]; + $if_context->loop_scope->vars_possibly_in_scope = [ + ...$vars_possibly_in_scope, + ...$if_context->loop_scope->vars_possibly_in_scope, + ]; } elseif (!$has_leaving_statements) { $if_scope->new_vars_possibly_in_scope = $vars_possibly_in_scope; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php index cfbe2a6928f..b14891ce0f9 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php @@ -363,9 +363,15 @@ public static function analyze( ); } - $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$if_scope->new_vars_possibly_in_scope]; - - $context->possibly_assigned_var_ids = [...$context->possibly_assigned_var_ids, ...$if_scope->possibly_assigned_var_ids ?: []]; + $context->vars_possibly_in_scope = [ + ...$context->vars_possibly_in_scope, + ...$if_scope->new_vars_possibly_in_scope, + ]; + + $context->possibly_assigned_var_ids = [ + ...$context->possibly_assigned_var_ids, + ...$if_scope->possibly_assigned_var_ids ?: [], + ]; // vars can only be defined/redefined if there was an else (defined in every block) $context->assigned_var_ids = array_merge( diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php index e0705a0cac4..9fb909fd8b0 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php @@ -139,7 +139,10 @@ public static function analyze( } } - $loop_parent_context->vars_possibly_in_scope = [...$continue_context->vars_possibly_in_scope, ...$loop_parent_context->vars_possibly_in_scope]; + $loop_parent_context->vars_possibly_in_scope = [ + ...$continue_context->vars_possibly_in_scope, + ...$loop_parent_context->vars_possibly_in_scope, + ]; } else { $original_parent_context = clone $loop_parent_context; @@ -267,7 +270,10 @@ public static function analyze( $continue_context->has_returned = false; - $loop_parent_context->vars_possibly_in_scope = [...$continue_context->vars_possibly_in_scope, ...$loop_parent_context->vars_possibly_in_scope]; + $loop_parent_context->vars_possibly_in_scope = [ + ...$continue_context->vars_possibly_in_scope, + ...$loop_parent_context->vars_possibly_in_scope, + ]; // if there are no changes to the types, no need to re-examine if (!$has_changes) { @@ -547,7 +553,10 @@ private static function updateLoopScopeContexts( } // merge vars possibly in scope at the end of each loop - $loop_context->vars_possibly_in_scope = [...$loop_context->vars_possibly_in_scope, ...$loop_scope->vars_possibly_in_scope]; + $loop_context->vars_possibly_in_scope = [ + ...$loop_context->vars_possibly_in_scope, + ...$loop_scope->vars_possibly_in_scope, + ]; } /** diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php index c3f5bc4f9ec..ee9d7cb1822 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php @@ -219,7 +219,10 @@ public static function analyze( $context->assigned_var_ids += $switch_scope->new_assigned_var_ids; } - $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$switch_scope->new_vars_possibly_in_scope]; + $context->vars_possibly_in_scope = [ + ...$context->vars_possibly_in_scope, + ...$switch_scope->new_vars_possibly_in_scope, + ]; //a switch can't return in all options without a default $context->has_returned = $all_options_returned && $has_default; diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php index 694515eb921..fa2fd99e653 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php @@ -103,7 +103,10 @@ public static function analyze( $while_context->loop_scope = null; if ($can_leave_loop) { - $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$while_context->vars_possibly_in_scope]; + $context->vars_possibly_in_scope = [ + ...$context->vars_possibly_in_scope, + ...$while_context->vars_possibly_in_scope, + ]; } elseif ($pre_context) { $context->vars_possibly_in_scope = $pre_context->vars_possibly_in_scope; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php index ec0967aee0a..5356280bd5e 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php @@ -188,11 +188,20 @@ public static function analyze( if ($context->if_body_context && !$context->inside_negation) { $if_body_context = $context->if_body_context; $context->vars_in_scope = $right_context->vars_in_scope; - $if_body_context->vars_in_scope = [...$if_body_context->vars_in_scope, ...$context->vars_in_scope]; + $if_body_context->vars_in_scope = [ + ...$if_body_context->vars_in_scope, + ...$context->vars_in_scope, + ]; - $if_body_context->cond_referenced_var_ids = [...$if_body_context->cond_referenced_var_ids, ...$context->cond_referenced_var_ids]; + $if_body_context->cond_referenced_var_ids = [ + ...$if_body_context->cond_referenced_var_ids, + ...$context->cond_referenced_var_ids, + ]; - $if_body_context->assigned_var_ids = [...$if_body_context->assigned_var_ids, ...$context->assigned_var_ids]; + $if_body_context->assigned_var_ids = [ + ...$if_body_context->assigned_var_ids, + ...$context->assigned_var_ids, + ]; $if_body_context->reconciled_expression_clauses = [ ...$if_body_context->reconciled_expression_clauses, @@ -203,7 +212,10 @@ public static function analyze( ), ]; - $if_body_context->vars_possibly_in_scope = [...$if_body_context->vars_possibly_in_scope, ...$context->vars_possibly_in_scope]; + $if_body_context->vars_possibly_in_scope = [ + ...$if_body_context->vars_possibly_in_scope, + ...$context->vars_possibly_in_scope, + ]; $if_body_context->updateChecks($context); } else { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php index d43c33936bd..e7134d07487 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php @@ -132,10 +132,16 @@ public static function analyze( } $left_referenced_var_ids = $left_context->cond_referenced_var_ids; - $left_context->cond_referenced_var_ids = [...$pre_referenced_var_ids, ...$left_referenced_var_ids]; + $left_context->cond_referenced_var_ids = [ + ...$pre_referenced_var_ids, + ...$left_referenced_var_ids, + ]; $left_assigned_var_ids = array_diff_key($left_context->assigned_var_ids, $pre_assigned_var_ids); - $left_context->assigned_var_ids = [...$pre_assigned_var_ids, ...$left_context->assigned_var_ids]; + $left_context->assigned_var_ids = [ + ...$pre_assigned_var_ids, + ...$left_context->assigned_var_ids, + ]; $left_referenced_var_ids = array_diff_key($left_referenced_var_ids, $left_assigned_var_ids); } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php index 671b151659b..9c574e7a0f8 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php @@ -210,7 +210,10 @@ static function (Clause $c) use ($mixed_var_ids, $cond_object_id): Clause { return false; } - $context->cond_referenced_var_ids = [...$context->cond_referenced_var_ids, ...$if_context->cond_referenced_var_ids]; + $context->cond_referenced_var_ids = [ + ...$context->cond_referenced_var_ids, + ...$if_context->cond_referenced_var_ids, + ]; } $t_else_context->clauses = Algebra::simplifyCNF( @@ -286,9 +289,16 @@ static function (Clause $c) use ($mixed_var_ids, $cond_object_id): Clause { } } - $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$if_context->vars_possibly_in_scope, ...$t_else_context->vars_possibly_in_scope]; + $context->vars_possibly_in_scope = [ + ...$context->vars_possibly_in_scope, + ...$if_context->vars_possibly_in_scope, + ...$t_else_context->vars_possibly_in_scope, + ]; - $context->cond_referenced_var_ids = [...$context->cond_referenced_var_ids, ...$t_else_context->cond_referenced_var_ids]; + $context->cond_referenced_var_ids = [ + ...$context->cond_referenced_var_ids, + ...$t_else_context->cond_referenced_var_ids, + ]; $lhs_type = null; $stmt_cond_type = $statements_analyzer->node_data->getType($stmt->cond); From 1175c71cd985518082d5a969c9a608692932cb54 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 14:50:10 +0200 Subject: [PATCH 29/63] Update --- src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php | 7 +++++-- .../Internal/Analyzer/Statements/Block/ForAnalyzer.php | 5 ++++- .../Analyzer/Statements/Block/ForeachAnalyzer.php | 10 ++++++++-- .../Analyzer/Statements/Block/LoopAnalyzer.php | 5 ++++- .../Codebase/AssertionsFromInheritanceResolver.php | 5 ++++- src/Psalm/Internal/DataFlow/Path.php | 8 ++++++-- src/Psalm/Internal/FileManipulation/CodeMigration.php | 9 +++++++-- .../Internal/LanguageServer/Server/TextDocument.php | 7 +++++-- src/Psalm/Internal/LanguageServer/Server/Workspace.php | 7 +++++-- .../Scanner/UnresolvedConstant/UnresolvedTernary.php | 7 +++++-- src/Psalm/Internal/Scope/IfConditionalScope.php | 9 +++++++-- .../Internal/Type/TypeAlias/LinkableTypeAlias.php | 9 +++++++-- src/Psalm/Internal/Type/TypeTokenizer.php | 4 +++- src/Psalm/Type/Atomic/TClassConstant.php | 7 +++++-- 14 files changed, 75 insertions(+), 24 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php index 83adbb7da94..40a6f778b25 100644 --- a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php @@ -91,8 +91,11 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer protected ClassLikeStorage $storage; - public function __construct(protected PhpParser\Node\Stmt\ClassLike $class, SourceAnalyzer $source, protected string $fq_class_name) - { + public function __construct( + protected PhpParser\Node\Stmt\ClassLike $class, + SourceAnalyzer $source, + protected string $fq_class_name, + ) { $this->source = $source; $this->file_analyzer = $source->getFileAnalyzer(); $codebase = $source->getCodebase(); diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php index 96c67cda896..b8e95b7d9e2 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php @@ -170,7 +170,10 @@ public static function analyze( $for_context->loop_scope = null; if ($can_leave_loop) { - $context->vars_possibly_in_scope = [...$context->vars_possibly_in_scope, ...$for_context->vars_possibly_in_scope]; + $context->vars_possibly_in_scope = [ + ...$context->vars_possibly_in_scope, + ...$for_context->vars_possibly_in_scope, + ]; } elseif ($pre_context) { $context->vars_possibly_in_scope = $pre_context->vars_possibly_in_scope; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php index f5e6c26d61d..c11dba95c61 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php @@ -548,7 +548,10 @@ public static function checkIteratorType( } } elseif ($iterator_atomic_type instanceof TIterable) { if ($iterator_atomic_type->extra_types) { - $iterator_atomic_types = [$iterator_atomic_type->setIntersectionTypes([]), ...$iterator_atomic_type->extra_types]; + $iterator_atomic_types = [ + $iterator_atomic_type->setIntersectionTypes([]), + ...$iterator_atomic_type->extra_types, + ]; } else { $iterator_atomic_types = [$iterator_atomic_type]; } @@ -728,7 +731,10 @@ public static function handleIterable( bool &$has_valid_iterator, ): void { if ($iterator_atomic_type->extra_types) { - $iterator_atomic_types = [$iterator_atomic_type->setIntersectionTypes([]), ...$iterator_atomic_type->extra_types]; + $iterator_atomic_types = [ + $iterator_atomic_type->setIntersectionTypes([]), + ...$iterator_atomic_type->extra_types, + ]; } else { $iterator_atomic_types = [$iterator_atomic_type]; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php index 9fb909fd8b0..60e3acaa964 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php @@ -442,7 +442,10 @@ public static function analyze( $loop_parent_context->removeVarFromConflictingClauses($var_id); } else { $loop_parent_context->vars_in_scope[$var_id] = - $loop_parent_context->vars_in_scope[$var_id]->setParentNodes([...$loop_parent_context->vars_in_scope[$var_id]->parent_nodes, ...$continue_context->vars_in_scope[$var_id]->parent_nodes]) + $loop_parent_context->vars_in_scope[$var_id]->setParentNodes([ + ...$loop_parent_context->vars_in_scope[$var_id]->parent_nodes, + ...$continue_context->vars_in_scope[$var_id]->parent_nodes, + ]) ; } } diff --git a/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php b/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php index 57c577e022e..594768af845 100644 --- a/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php +++ b/src/Psalm/Internal/Codebase/AssertionsFromInheritanceResolver.php @@ -33,7 +33,10 @@ public function resolve( $method_name_lc = strtolower($method_storage->cased_name ?? ''); $assertions = $method_storage->assertions; - $inherited_classes_and_interfaces = array_values(array_filter([...$called_class->parent_classes, ...$called_class->class_implements], fn(string $classOrInterface) => $this->codebase->classOrInterfaceOrEnumExists($classOrInterface))); + $inherited_classes_and_interfaces = array_values(array_filter([ + ...$called_class->parent_classes, + ...$called_class->class_implements, + ], fn(string $classOrInterface) => $this->codebase->classOrInterfaceOrEnumExists($classOrInterface))); foreach ($inherited_classes_and_interfaces as $potential_assertion_providing_class) { $potential_assertion_providing_classlike_storage = $this->codebase->classlike_storage_provider->get( diff --git a/src/Psalm/Internal/DataFlow/Path.php b/src/Psalm/Internal/DataFlow/Path.php index 083ac990601..870d7ed07a5 100644 --- a/src/Psalm/Internal/DataFlow/Path.php +++ b/src/Psalm/Internal/DataFlow/Path.php @@ -18,7 +18,11 @@ final class Path * @param ?array $unescaped_taints * @param ?array $escaped_taints */ - public function __construct(public string $type, public int $length, public ?array $unescaped_taints = null, public ?array $escaped_taints = null) - { + public function __construct( + public string $type, + public int $length, + public ?array $unescaped_taints = null, + public ?array $escaped_taints = null, + ) { } } diff --git a/src/Psalm/Internal/FileManipulation/CodeMigration.php b/src/Psalm/Internal/FileManipulation/CodeMigration.php index 61ca6230fb2..0c98ca2867d 100644 --- a/src/Psalm/Internal/FileManipulation/CodeMigration.php +++ b/src/Psalm/Internal/FileManipulation/CodeMigration.php @@ -14,7 +14,12 @@ final class CodeMigration { use ImmutableNonCloneableTrait; - public function __construct(public string $source_file_path, public int $source_start, public int $source_end, public string $destination_file_path, public int $destination_start) - { + public function __construct( + public string $source_file_path, + public int $source_start, + public int $source_end, + public string $destination_file_path, + public int $destination_start, + ) { } } diff --git a/src/Psalm/Internal/LanguageServer/Server/TextDocument.php b/src/Psalm/Internal/LanguageServer/Server/TextDocument.php index c51091ed976..7d35bd9cfab 100644 --- a/src/Psalm/Internal/LanguageServer/Server/TextDocument.php +++ b/src/Psalm/Internal/LanguageServer/Server/TextDocument.php @@ -38,8 +38,11 @@ */ final class TextDocument { - public function __construct(protected LanguageServer $server, protected Codebase $codebase, protected ProjectAnalyzer $project_analyzer) - { + public function __construct( + protected LanguageServer $server, + protected Codebase $codebase, + protected ProjectAnalyzer $project_analyzer, + ) { } /** diff --git a/src/Psalm/Internal/LanguageServer/Server/Workspace.php b/src/Psalm/Internal/LanguageServer/Server/Workspace.php index d0f2fd01735..a4f3aef6ca4 100644 --- a/src/Psalm/Internal/LanguageServer/Server/Workspace.php +++ b/src/Psalm/Internal/LanguageServer/Server/Workspace.php @@ -25,8 +25,11 @@ */ final class Workspace { - public function __construct(protected LanguageServer $server, protected Codebase $codebase, protected ProjectAnalyzer $project_analyzer) - { + public function __construct( + protected LanguageServer $server, + protected Codebase $codebase, + protected ProjectAnalyzer $project_analyzer, + ) { } /** diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php index 3e1cf7ca913..f2208477f83 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php @@ -15,7 +15,10 @@ final class UnresolvedTernary extends UnresolvedConstantComponent { use ImmutableNonCloneableTrait; - public function __construct(public UnresolvedConstantComponent $cond, public ?UnresolvedConstantComponent $if, public UnresolvedConstantComponent $else) - { + public function __construct( + public UnresolvedConstantComponent $cond, + public ?UnresolvedConstantComponent $if, + public UnresolvedConstantComponent $else, + ) { } } diff --git a/src/Psalm/Internal/Scope/IfConditionalScope.php b/src/Psalm/Internal/Scope/IfConditionalScope.php index 502979c06e9..0c7868570a3 100644 --- a/src/Psalm/Internal/Scope/IfConditionalScope.php +++ b/src/Psalm/Internal/Scope/IfConditionalScope.php @@ -17,7 +17,12 @@ final class IfConditionalScope * @param array $assigned_in_conditional_var_ids * @param list $entry_clauses */ - public function __construct(public Context $if_context, public Context $post_if_context, public array $cond_referenced_var_ids, public array $assigned_in_conditional_var_ids, public array $entry_clauses) - { + public function __construct( + public Context $if_context, + public Context $post_if_context, + public array $cond_referenced_var_ids, + public array $assigned_in_conditional_var_ids, + public array $entry_clauses + ) { } } diff --git a/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php b/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php index 9ccc65ae323..e5979d438e3 100644 --- a/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php +++ b/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php @@ -15,7 +15,12 @@ final class LinkableTypeAlias implements TypeAlias { use ImmutableNonCloneableTrait; - public function __construct(public string $declaring_fq_classlike_name, public string $alias_name, public int $line_number, public int $start_offset, public int $end_offset) - { + public function __construct( + public string $declaring_fq_classlike_name, + public string $alias_name, + public int $line_number, + public int $start_offset, + public int $end_offset, + ) { } } diff --git a/src/Psalm/Internal/Type/TypeTokenizer.php b/src/Psalm/Internal/Type/TypeTokenizer.php index 0a647028608..57bb5c8b6c8 100644 --- a/src/Psalm/Internal/Type/TypeTokenizer.php +++ b/src/Psalm/Internal/Type/TypeTokenizer.php @@ -318,7 +318,9 @@ public static function fixScalarTerms( ): string { $type_string_lc = strtolower($type_string); return match ($type_string_lc) { - 'int', 'void', 'float', 'string', 'bool', 'callable', 'iterable', 'array', 'object', 'true', 'false', 'null', 'mixed' => $type_string_lc, + 'int', 'void', 'float', 'string', 'bool', + 'callable', 'iterable', 'array', 'object', + 'true', 'false', 'null', 'mixed' => $type_string_lc, default => match ($type_string) { 'boolean' => $analysis_php_version_id !== null ? $type_string : 'bool', 'integer' => $analysis_php_version_id !== null ? $type_string : 'int', diff --git a/src/Psalm/Type/Atomic/TClassConstant.php b/src/Psalm/Type/Atomic/TClassConstant.php index 7dfbba4a323..21e8c0a25a5 100644 --- a/src/Psalm/Type/Atomic/TClassConstant.php +++ b/src/Psalm/Type/Atomic/TClassConstant.php @@ -14,8 +14,11 @@ */ final class TClassConstant extends Atomic { - public function __construct(public string $fq_classlike_name, public string $const_name, bool $from_docblock = false) - { + public function __construct( + public string $fq_classlike_name, + public string $const_name, + bool $from_docblock = false, + ) { parent::__construct($from_docblock); } From cb48b00d1c978e2669880f6efe0a80f96e0fa6b2 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 14:51:48 +0200 Subject: [PATCH 30/63] cs-fix --- src/Psalm/FileManipulation.php | 9 +++++++-- src/Psalm/Internal/Scope/IfConditionalScope.php | 2 +- src/Psalm/Report/ByIssueLevelAndTypeReport.php | 4 +++- src/Psalm/Report/ConsoleReport.php | 4 +++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Psalm/FileManipulation.php b/src/Psalm/FileManipulation.php index fbc8bcfca4c..f475b0b6855 100644 --- a/src/Psalm/FileManipulation.php +++ b/src/Psalm/FileManipulation.php @@ -12,8 +12,13 @@ final class FileManipulation { - public function __construct(public int $start, public int $end, public string $insertion_text, public bool $preserve_indentation = false, public bool $remove_trailing_newline = false) - { + public function __construct( + public int $start, + public int $end, + public string $insertion_text, + public bool $preserve_indentation = false, + public bool $remove_trailing_newline = false, + ) { } public function getKey(): string diff --git a/src/Psalm/Internal/Scope/IfConditionalScope.php b/src/Psalm/Internal/Scope/IfConditionalScope.php index 0c7868570a3..4db024f4c22 100644 --- a/src/Psalm/Internal/Scope/IfConditionalScope.php +++ b/src/Psalm/Internal/Scope/IfConditionalScope.php @@ -22,7 +22,7 @@ public function __construct( public Context $post_if_context, public array $cond_referenced_var_ids, public array $assigned_in_conditional_var_ids, - public array $entry_clauses + public array $entry_clauses, ) { } } diff --git a/src/Psalm/Report/ByIssueLevelAndTypeReport.php b/src/Psalm/Report/ByIssueLevelAndTypeReport.php index a4c6975d40e..69445ce89e6 100644 --- a/src/Psalm/Report/ByIssueLevelAndTypeReport.php +++ b/src/Psalm/Report/ByIssueLevelAndTypeReport.php @@ -166,7 +166,9 @@ private function getFileReference(IssueData|DataFlowNodeData $data): string if (null === $this->link_format) { // if xdebug is not enabled, use `get_cfg_var` to get the value directly from php.ini - $this->link_format = (ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: 'file://%f#L%l'; + $this->link_format = ( + ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') + ) ?: 'file://%f#L%l'; } $link = strtr($this->link_format, ['%f' => $data->file_path, '%l' => $data->line_from]); diff --git a/src/Psalm/Report/ConsoleReport.php b/src/Psalm/Report/ConsoleReport.php index f8a4b4e2441..7499ffcb162 100644 --- a/src/Psalm/Report/ConsoleReport.php +++ b/src/Psalm/Report/ConsoleReport.php @@ -134,7 +134,9 @@ private function getFileReference(IssueData|DataFlowNodeData $data): string if (null === $this->link_format) { // if xdebug is not enabled, use `get_cfg_var` to get the value directly from php.ini - $this->link_format = (ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: 'file://%f#L%l'; + $this->link_format = ( + ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') + ) ?: 'file://%f#L%l'; } $link = strtr($this->link_format, ['%f' => $data->file_path, '%l' => $data->line_from]); From 4a433d34b416126965b6888dd78d33d16c15e144 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 15:02:19 +0200 Subject: [PATCH 31/63] More readonly props --- src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php | 2 +- src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php | 2 +- src/Psalm/Storage/Assertion/DoesNotHaveMethod.php | 2 +- src/Psalm/Storage/Assertion/HasArrayKey.php | 2 +- src/Psalm/Storage/Assertion/HasAtLeastCount.php | 2 +- src/Psalm/Storage/Assertion/HasExactCount.php | 2 +- src/Psalm/Storage/Assertion/HasMethod.php | 2 +- src/Psalm/Storage/Assertion/InArray.php | 2 +- src/Psalm/Storage/Assertion/IsAClass.php | 2 +- src/Psalm/Storage/Assertion/IsClassEqual.php | 2 +- src/Psalm/Storage/Assertion/IsClassNotEqual.php | 2 +- src/Psalm/Storage/Assertion/IsGreaterThan.php | 2 +- src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php | 2 +- src/Psalm/Storage/Assertion/IsIdentical.php | 2 +- src/Psalm/Storage/Assertion/IsLessThan.php | 2 +- src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php | 2 +- src/Psalm/Storage/Assertion/IsLooselyEqual.php | 2 +- src/Psalm/Storage/Assertion/IsNotAClass.php | 2 +- src/Psalm/Storage/Assertion/IsNotCountable.php | 2 +- src/Psalm/Storage/Assertion/IsNotIdentical.php | 2 +- src/Psalm/Storage/Assertion/IsNotLooselyEqual.php | 2 +- src/Psalm/Storage/Assertion/IsNotType.php | 2 +- src/Psalm/Storage/Assertion/IsType.php | 2 +- src/Psalm/Storage/Assertion/NestedAssertions.php | 2 +- src/Psalm/Storage/Assertion/NonEmptyCountable.php | 2 +- src/Psalm/Storage/Assertion/NotInArray.php | 2 +- src/Psalm/Storage/Assertion/NotNestedAssertions.php | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php b/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php index f7f23955ffe..01e55a42192 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php @@ -12,7 +12,7 @@ final class DoesNotHaveAtLeastCount extends Assertion { /** @param positive-int $count */ - public function __construct(public int $count) + public function __construct(public readonly int $count) { } diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php b/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php index 39727d14979..125b0bd8f1e 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php @@ -12,7 +12,7 @@ final class DoesNotHaveExactCount extends Assertion { /** @param positive-int $count */ - public function __construct(public int $count) + public function __construct(public readonly int $count) { } diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php b/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php index a760247603a..72b5e0e20ba 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php @@ -11,7 +11,7 @@ */ final class DoesNotHaveMethod extends Assertion { - public function __construct(public string $method) + public function __construct(public readonly string $method) { } diff --git a/src/Psalm/Storage/Assertion/HasArrayKey.php b/src/Psalm/Storage/Assertion/HasArrayKey.php index 1326f09510e..e98f0d9f25a 100644 --- a/src/Psalm/Storage/Assertion/HasArrayKey.php +++ b/src/Psalm/Storage/Assertion/HasArrayKey.php @@ -12,7 +12,7 @@ */ final class HasArrayKey extends Assertion { - public function __construct(public readonly string $key) + public function __construct(public readonly readonly string $key) { } diff --git a/src/Psalm/Storage/Assertion/HasAtLeastCount.php b/src/Psalm/Storage/Assertion/HasAtLeastCount.php index c15a40435be..479d5191866 100644 --- a/src/Psalm/Storage/Assertion/HasAtLeastCount.php +++ b/src/Psalm/Storage/Assertion/HasAtLeastCount.php @@ -12,7 +12,7 @@ final class HasAtLeastCount extends Assertion { /** @param positive-int $count */ - public function __construct(public int $count) + public function __construct(public readonly int $count) { } diff --git a/src/Psalm/Storage/Assertion/HasExactCount.php b/src/Psalm/Storage/Assertion/HasExactCount.php index 41f03b627e1..9bb5b8edda5 100644 --- a/src/Psalm/Storage/Assertion/HasExactCount.php +++ b/src/Psalm/Storage/Assertion/HasExactCount.php @@ -12,7 +12,7 @@ final class HasExactCount extends Assertion { /** @param positive-int $count */ - public function __construct(public int $count) + public function __construct(public readonly int $count) { } diff --git a/src/Psalm/Storage/Assertion/HasMethod.php b/src/Psalm/Storage/Assertion/HasMethod.php index 1d18a3a1933..87e090cadcb 100644 --- a/src/Psalm/Storage/Assertion/HasMethod.php +++ b/src/Psalm/Storage/Assertion/HasMethod.php @@ -11,7 +11,7 @@ */ final class HasMethod extends Assertion { - public function __construct(public string $method) + public function __construct(public readonly string $method) { } diff --git a/src/Psalm/Storage/Assertion/InArray.php b/src/Psalm/Storage/Assertion/InArray.php index 0ef928f5bd9..021f18f1d58 100644 --- a/src/Psalm/Storage/Assertion/InArray.php +++ b/src/Psalm/Storage/Assertion/InArray.php @@ -12,7 +12,7 @@ */ final class InArray extends Assertion { - public function __construct(public Union $type) + public function __construct(public readonly Union $type) { } diff --git a/src/Psalm/Storage/Assertion/IsAClass.php b/src/Psalm/Storage/Assertion/IsAClass.php index daf178c5f24..1909c7eb000 100644 --- a/src/Psalm/Storage/Assertion/IsAClass.php +++ b/src/Psalm/Storage/Assertion/IsAClass.php @@ -13,7 +13,7 @@ final class IsAClass extends Assertion { /** @param Atomic\TTemplateParamClass|Atomic\TNamedObject $type */ - public function __construct(public Atomic $type, public bool $allow_string) + public function __construct(public readonly Atomic $type, public readonly bool $allow_string) { } diff --git a/src/Psalm/Storage/Assertion/IsClassEqual.php b/src/Psalm/Storage/Assertion/IsClassEqual.php index e0dce8d388c..fc117d1506a 100644 --- a/src/Psalm/Storage/Assertion/IsClassEqual.php +++ b/src/Psalm/Storage/Assertion/IsClassEqual.php @@ -11,7 +11,7 @@ */ final class IsClassEqual extends Assertion { - public function __construct(public string $type) + public function __construct(public readonly string $type) { } diff --git a/src/Psalm/Storage/Assertion/IsClassNotEqual.php b/src/Psalm/Storage/Assertion/IsClassNotEqual.php index 67044932a47..e5ccaa42130 100644 --- a/src/Psalm/Storage/Assertion/IsClassNotEqual.php +++ b/src/Psalm/Storage/Assertion/IsClassNotEqual.php @@ -11,7 +11,7 @@ */ final class IsClassNotEqual extends Assertion { - public function __construct(public string $type) + public function __construct(public readonly string $type) { } diff --git a/src/Psalm/Storage/Assertion/IsGreaterThan.php b/src/Psalm/Storage/Assertion/IsGreaterThan.php index 28d7122767d..fa3087475e3 100644 --- a/src/Psalm/Storage/Assertion/IsGreaterThan.php +++ b/src/Psalm/Storage/Assertion/IsGreaterThan.php @@ -11,7 +11,7 @@ */ final class IsGreaterThan extends Assertion { - public function __construct(public int $value) + public function __construct(public readonly int $value) { } diff --git a/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php b/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php index 6e3f16d39ad..3d4dde1bd92 100644 --- a/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php +++ b/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php @@ -11,7 +11,7 @@ */ final class IsGreaterThanOrEqualTo extends Assertion { - public function __construct(public int $value) + public function __construct(public readonly int $value) { } diff --git a/src/Psalm/Storage/Assertion/IsIdentical.php b/src/Psalm/Storage/Assertion/IsIdentical.php index 90193fc9ca2..de3c3db39f5 100644 --- a/src/Psalm/Storage/Assertion/IsIdentical.php +++ b/src/Psalm/Storage/Assertion/IsIdentical.php @@ -12,7 +12,7 @@ */ final class IsIdentical extends Assertion { - public function __construct(public Atomic $type) + public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsLessThan.php b/src/Psalm/Storage/Assertion/IsLessThan.php index d4236b65058..508b3f8031c 100644 --- a/src/Psalm/Storage/Assertion/IsLessThan.php +++ b/src/Psalm/Storage/Assertion/IsLessThan.php @@ -11,7 +11,7 @@ */ final class IsLessThan extends Assertion { - public function __construct(public int $value) + public function __construct(public readonly int $value) { } diff --git a/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php b/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php index 5250d2da78d..d6934334e71 100644 --- a/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php +++ b/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php @@ -11,7 +11,7 @@ */ final class IsLessThanOrEqualTo extends Assertion { - public function __construct(public int $value) + public function __construct(public readonly int $value) { } diff --git a/src/Psalm/Storage/Assertion/IsLooselyEqual.php b/src/Psalm/Storage/Assertion/IsLooselyEqual.php index 5fdd85d4ec9..a5d5b6ac4ed 100644 --- a/src/Psalm/Storage/Assertion/IsLooselyEqual.php +++ b/src/Psalm/Storage/Assertion/IsLooselyEqual.php @@ -12,7 +12,7 @@ */ final class IsLooselyEqual extends Assertion { - public function __construct(public Atomic $type) + public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsNotAClass.php b/src/Psalm/Storage/Assertion/IsNotAClass.php index a94327a88b3..80303df369c 100644 --- a/src/Psalm/Storage/Assertion/IsNotAClass.php +++ b/src/Psalm/Storage/Assertion/IsNotAClass.php @@ -13,7 +13,7 @@ final class IsNotAClass extends Assertion { /** @param Atomic\TTemplateParamClass|Atomic\TNamedObject $type */ - public function __construct(public Atomic $type, public bool $allow_string) + public function __construct(public readonly Atomic $type, public readonly bool $allow_string) { } diff --git a/src/Psalm/Storage/Assertion/IsNotCountable.php b/src/Psalm/Storage/Assertion/IsNotCountable.php index 5f11cf6df6b..e76a65ba035 100644 --- a/src/Psalm/Storage/Assertion/IsNotCountable.php +++ b/src/Psalm/Storage/Assertion/IsNotCountable.php @@ -11,7 +11,7 @@ */ final class IsNotCountable extends Assertion { - public function __construct(public readonly bool $is_negatable) + public function __construct(public readonly readonly bool $is_negatable) { } diff --git a/src/Psalm/Storage/Assertion/IsNotIdentical.php b/src/Psalm/Storage/Assertion/IsNotIdentical.php index 6dcfa2b908d..11c482d1c04 100644 --- a/src/Psalm/Storage/Assertion/IsNotIdentical.php +++ b/src/Psalm/Storage/Assertion/IsNotIdentical.php @@ -12,7 +12,7 @@ */ final class IsNotIdentical extends Assertion { - public function __construct(public Atomic $type) + public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php b/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php index 0a1f9f1abd3..bb8d4ee7d0e 100644 --- a/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php +++ b/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php @@ -12,7 +12,7 @@ */ final class IsNotLooselyEqual extends Assertion { - public function __construct(public Atomic $type) + public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsNotType.php b/src/Psalm/Storage/Assertion/IsNotType.php index ff07df64287..1d51e037017 100644 --- a/src/Psalm/Storage/Assertion/IsNotType.php +++ b/src/Psalm/Storage/Assertion/IsNotType.php @@ -12,7 +12,7 @@ */ final class IsNotType extends Assertion { - public function __construct(public Atomic $type) + public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsType.php b/src/Psalm/Storage/Assertion/IsType.php index f1e5f1e3d51..70920806743 100644 --- a/src/Psalm/Storage/Assertion/IsType.php +++ b/src/Psalm/Storage/Assertion/IsType.php @@ -12,7 +12,7 @@ */ final class IsType extends Assertion { - public function __construct(public Atomic $type) + public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/NestedAssertions.php b/src/Psalm/Storage/Assertion/NestedAssertions.php index b8281f9d22f..353807d2401 100644 --- a/src/Psalm/Storage/Assertion/NestedAssertions.php +++ b/src/Psalm/Storage/Assertion/NestedAssertions.php @@ -16,7 +16,7 @@ final class NestedAssertions extends Assertion { /** @param array>> $assertions */ - public function __construct(public array $assertions) + public function __construct(public readonly array $assertions) { } diff --git a/src/Psalm/Storage/Assertion/NonEmptyCountable.php b/src/Psalm/Storage/Assertion/NonEmptyCountable.php index a36bffdd2a6..3d45a4302cc 100644 --- a/src/Psalm/Storage/Assertion/NonEmptyCountable.php +++ b/src/Psalm/Storage/Assertion/NonEmptyCountable.php @@ -11,7 +11,7 @@ */ final class NonEmptyCountable extends Assertion { - public function __construct(public readonly bool $is_negatable) + public function __construct(public readonly readonly bool $is_negatable) { } diff --git a/src/Psalm/Storage/Assertion/NotInArray.php b/src/Psalm/Storage/Assertion/NotInArray.php index 17c385f8825..db79e877c4e 100644 --- a/src/Psalm/Storage/Assertion/NotInArray.php +++ b/src/Psalm/Storage/Assertion/NotInArray.php @@ -13,7 +13,7 @@ final class NotInArray extends Assertion { public function __construct( - public readonly Union $type, + public readonly readonly Union $type, ) { } diff --git a/src/Psalm/Storage/Assertion/NotNestedAssertions.php b/src/Psalm/Storage/Assertion/NotNestedAssertions.php index b69ec8f5f69..4ca457dcf02 100644 --- a/src/Psalm/Storage/Assertion/NotNestedAssertions.php +++ b/src/Psalm/Storage/Assertion/NotNestedAssertions.php @@ -16,7 +16,7 @@ final class NotNestedAssertions extends Assertion { /** @param array>> $assertions */ - public function __construct(public array $assertions) + public function __construct(public readonly array $assertions) { } From f1d784336fc0773f1869b60b8b6a766ede28b8ec Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 15:16:35 +0200 Subject: [PATCH 32/63] Make more properties readonly --- .../Internal/Analyzer/AttributesAnalyzer.php | 2 +- .../Internal/Analyzer/DataFlowNodeData.php | 22 +++++++++---------- .../Call/HighOrderFunctionArgInfo.php | 2 +- src/Psalm/Internal/DataFlow/Path.php | 8 +++---- src/Psalm/Internal/Diff/DiffElem.php | 6 ++--- .../FileManipulation/CodeMigration.php | 10 ++++----- .../Internal/Fork/ForkProcessDoneMessage.php | 2 +- .../Internal/Fork/ForkProcessErrorMessage.php | 2 +- .../Internal/Fork/ForkTaskDoneMessage.php | 2 +- src/Psalm/Internal/MethodIdentifier.php | 2 +- .../UnresolvedConstant/ArrayOffsetFetch.php | 2 +- .../UnresolvedConstant/ArraySpread.php | 2 +- .../Scanner/UnresolvedConstant/ArrayValue.php | 2 +- .../UnresolvedConstant/ClassConstant.php | 2 +- .../Scanner/UnresolvedConstant/Constant.php | 2 +- .../UnresolvedConstant/EnumPropertyFetch.php | 2 +- .../UnresolvedConstant/KeyValuePair.php | 2 +- .../UnresolvedConstant/ScalarValue.php | 2 +- .../UnresolvedConstant/UnresolvedBinaryOp.php | 2 +- .../UnresolvedConstant/UnresolvedTernary.php | 6 ++--- .../Type/TypeAlias/InlineTypeAlias.php | 2 +- .../Type/TypeAlias/LinkableTypeAlias.php | 10 ++++----- src/Psalm/Storage/Assertion/HasArrayKey.php | 2 +- .../Storage/Assertion/IsNotCountable.php | 2 +- .../Storage/Assertion/NonEmptyCountable.php | 2 +- src/Psalm/Storage/Assertion/NotInArray.php | 2 +- src/Psalm/Storage/AttributeArg.php | 6 ++--- src/Psalm/Storage/AttributeStorage.php | 8 +++---- src/Psalm/Storage/ClassConstantStorage.php | 20 ++++++++--------- 29 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/AttributesAnalyzer.php b/src/Psalm/Internal/Analyzer/AttributesAnalyzer.php index 9f3e94472f8..5d1eaafd2bb 100644 --- a/src/Psalm/Internal/Analyzer/AttributesAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/AttributesAnalyzer.php @@ -264,7 +264,7 @@ private static function getAttributeClassFlags( return self::TARGET_ALL; // Defaults to TARGET_ALL } - $first_arg = reset($attribute_attribute->args); + $first_arg = $attribute_attribute->args[array_key_first($attribute_attribute->args)]; $first_arg_type = $first_arg->type; diff --git a/src/Psalm/Internal/Analyzer/DataFlowNodeData.php b/src/Psalm/Internal/Analyzer/DataFlowNodeData.php index 4e13c5b0a7f..c5711d701ad 100644 --- a/src/Psalm/Internal/Analyzer/DataFlowNodeData.php +++ b/src/Psalm/Internal/Analyzer/DataFlowNodeData.php @@ -15,17 +15,17 @@ final class DataFlowNodeData use ImmutableNonCloneableTrait; public function __construct( - public string $label, - public int $line_from, - public int $line_to, - public string $file_name, - public string $file_path, - public string $snippet, - public int $from, - public int $to, - public int $snippet_from, - public int $column_from, - public int $column_to, + public readonly string $label, + public readonly int $line_from, + public readonly int $line_to, + public readonly string $file_name, + public readonly string $file_path, + public readonly string $snippet, + public readonly int $from, + public readonly int $to, + public readonly int $snippet_from, + public readonly int $column_from, + public readonly int $column_to, ) { } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php index 6b3203ab3ba..54921838c0c 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/HighOrderFunctionArgInfo.php @@ -27,7 +27,7 @@ final class HighOrderFunctionArgInfo */ public function __construct( private readonly string $type, - private readonly FunctionLikeStorage $function_storage, + private functionLikeStorage $function_storage, private readonly ?ClassLikeStorage $class_storage = null, ) { } diff --git a/src/Psalm/Internal/DataFlow/Path.php b/src/Psalm/Internal/DataFlow/Path.php index 870d7ed07a5..785bb8e511a 100644 --- a/src/Psalm/Internal/DataFlow/Path.php +++ b/src/Psalm/Internal/DataFlow/Path.php @@ -19,10 +19,10 @@ final class Path * @param ?array $escaped_taints */ public function __construct( - public string $type, - public int $length, - public ?array $unescaped_taints = null, - public ?array $escaped_taints = null, + public readonly string $type, + public readonly int $length, + public readonly ?array $unescaped_taints = null, + public readonly ?array $escaped_taints = null, ) { } } diff --git a/src/Psalm/Internal/Diff/DiffElem.php b/src/Psalm/Internal/Diff/DiffElem.php index 4ea886f7927..270c00aa332 100644 --- a/src/Psalm/Internal/Diff/DiffElem.php +++ b/src/Psalm/Internal/Diff/DiffElem.php @@ -22,11 +22,11 @@ final class DiffElem public function __construct( /** @var int One of the TYPE_* constants */ - public int $type, + public readonly int $type, /** @var mixed Is null for add operations */ - public mixed $old, + public readonly mixed $old, /** @var mixed Is null for remove operations */ - public mixed $new, + public readonly mixed $new, ) { } } diff --git a/src/Psalm/Internal/FileManipulation/CodeMigration.php b/src/Psalm/Internal/FileManipulation/CodeMigration.php index 0c98ca2867d..980fa64b088 100644 --- a/src/Psalm/Internal/FileManipulation/CodeMigration.php +++ b/src/Psalm/Internal/FileManipulation/CodeMigration.php @@ -15,11 +15,11 @@ final class CodeMigration use ImmutableNonCloneableTrait; public function __construct( - public string $source_file_path, - public int $source_start, - public int $source_end, - public string $destination_file_path, - public int $destination_start, + public readonly string $source_file_path, + public readonly int $source_start, + public readonly int $source_end, + public readonly string $destination_file_path, + public readonly int $destination_start, ) { } } diff --git a/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php b/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php index bd595572044..0baea064884 100644 --- a/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php +++ b/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php @@ -14,7 +14,7 @@ final class ForkProcessDoneMessage implements ForkMessage { use ImmutableNonCloneableTrait; - public function __construct(public mixed $data) + public function __construct(public readonly mixed $data) { } } diff --git a/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php b/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php index 3bec3754a91..e0ba5e0ba16 100644 --- a/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php +++ b/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php @@ -14,7 +14,7 @@ final class ForkProcessErrorMessage implements ForkMessage { use ImmutableNonCloneableTrait; - public function __construct(public string $message) + public function __construct(public readonly string $message) { } } diff --git a/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php b/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php index 2959f472484..6cd9ccd09f1 100644 --- a/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php +++ b/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php @@ -14,7 +14,7 @@ final class ForkTaskDoneMessage implements ForkMessage { use ImmutableNonCloneableTrait; - public function __construct(public mixed $data) + public function __construct(public readonly mixed $data) { } } diff --git a/src/Psalm/Internal/MethodIdentifier.php b/src/Psalm/Internal/MethodIdentifier.php index fd4547e4580..ea317df69e6 100644 --- a/src/Psalm/Internal/MethodIdentifier.php +++ b/src/Psalm/Internal/MethodIdentifier.php @@ -25,7 +25,7 @@ final class MethodIdentifier implements Stringable /** * @param lowercase-string $method_name */ - public function __construct(public string $fq_class_name, public string $method_name) + public function __construct(public readonly string $fq_class_name, public readonly string $method_name) { } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php index 5d00c814497..e437117571d 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php @@ -12,7 +12,7 @@ */ final class ArrayOffsetFetch extends UnresolvedConstantComponent { - public function __construct(public UnresolvedConstantComponent $array, public UnresolvedConstantComponent $offset) + public function __construct(public readonly UnresolvedConstantComponent $array, public readonly UnresolvedConstantComponent $offset) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArraySpread.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArraySpread.php index 8861350a971..ca03b3a54db 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArraySpread.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArraySpread.php @@ -12,7 +12,7 @@ */ final class ArraySpread extends UnresolvedConstantComponent { - public function __construct(public UnresolvedConstantComponent $array) + public function __construct(public readonly UnresolvedConstantComponent $array) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php index 8ae8fd24f2a..6aa4df4008a 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php @@ -13,7 +13,7 @@ final class ArrayValue extends UnresolvedConstantComponent { /** @param list $entries */ - public function __construct(public array $entries) + public function __construct(public readonly array $entries) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php index d1bbc75d198..5833c76a45c 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php @@ -12,7 +12,7 @@ */ final class ClassConstant extends UnresolvedConstantComponent { - public function __construct(public string $fqcln, public string $name) + public function __construct(public readonly string $fqcln, public readonly string $name) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php index fcd76336eb9..250f03a1b87 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php @@ -12,7 +12,7 @@ */ final class Constant extends UnresolvedConstantComponent { - public function __construct(public string $name, public bool $is_fully_qualified) + public function __construct(public readonly string $name, public readonly bool $is_fully_qualified) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/EnumPropertyFetch.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/EnumPropertyFetch.php index 44f06bf4f12..26a2c8844e1 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/EnumPropertyFetch.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/EnumPropertyFetch.php @@ -12,7 +12,7 @@ */ abstract class EnumPropertyFetch extends UnresolvedConstantComponent { - public function __construct(public string $fqcln, public string $case) + public function __construct(public readonly string $fqcln, public readonly string $case) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php index 6501589a782..34c3c9455b7 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php @@ -12,7 +12,7 @@ */ final class KeyValuePair extends UnresolvedConstantComponent { - public function __construct(public ?UnresolvedConstantComponent $key, public UnresolvedConstantComponent $value) + public function __construct(public readonly ?UnresolvedConstantComponent $key, public readonly UnresolvedConstantComponent $value) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php index de23446a81b..73d12f96f7d 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php @@ -12,7 +12,7 @@ */ final class ScalarValue extends UnresolvedConstantComponent { - public function __construct(public string|int|float|bool|null $value) + public function __construct(public readonly string|int|float|bool|null $value) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php index 45c4791d731..ad316011299 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php @@ -15,7 +15,7 @@ abstract class UnresolvedBinaryOp extends UnresolvedConstantComponent { use ImmutableNonCloneableTrait; - public function __construct(public UnresolvedConstantComponent $left, public UnresolvedConstantComponent $right) + public function __construct(public readonly UnresolvedConstantComponent $left, public readonly UnresolvedConstantComponent $right) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php index f2208477f83..623bae4b6d8 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php @@ -16,9 +16,9 @@ final class UnresolvedTernary extends UnresolvedConstantComponent use ImmutableNonCloneableTrait; public function __construct( - public UnresolvedConstantComponent $cond, - public ?UnresolvedConstantComponent $if, - public UnresolvedConstantComponent $else, + public readonly UnresolvedConstantComponent $cond, + public readonly ?UnresolvedConstantComponent $if, + public readonly UnresolvedConstantComponent $else, ) { } } diff --git a/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php b/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php index 1571956ee6e..4a6bd27037c 100644 --- a/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php +++ b/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php @@ -18,7 +18,7 @@ final class InlineTypeAlias implements TypeAlias /** * @param list $replacement_tokens */ - public function __construct(public array $replacement_tokens) + public function __construct(public readonly array $replacement_tokens) { } } diff --git a/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php b/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php index e5979d438e3..e3a35026991 100644 --- a/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php +++ b/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php @@ -16,11 +16,11 @@ final class LinkableTypeAlias implements TypeAlias use ImmutableNonCloneableTrait; public function __construct( - public string $declaring_fq_classlike_name, - public string $alias_name, - public int $line_number, - public int $start_offset, - public int $end_offset, + public readonly string $declaring_fq_classlike_name, + public readonly string $alias_name, + public readonly int $line_number, + public readonly int $start_offset, + public readonly int $end_offset, ) { } } diff --git a/src/Psalm/Storage/Assertion/HasArrayKey.php b/src/Psalm/Storage/Assertion/HasArrayKey.php index e98f0d9f25a..1326f09510e 100644 --- a/src/Psalm/Storage/Assertion/HasArrayKey.php +++ b/src/Psalm/Storage/Assertion/HasArrayKey.php @@ -12,7 +12,7 @@ */ final class HasArrayKey extends Assertion { - public function __construct(public readonly readonly string $key) + public function __construct(public readonly string $key) { } diff --git a/src/Psalm/Storage/Assertion/IsNotCountable.php b/src/Psalm/Storage/Assertion/IsNotCountable.php index e76a65ba035..5f11cf6df6b 100644 --- a/src/Psalm/Storage/Assertion/IsNotCountable.php +++ b/src/Psalm/Storage/Assertion/IsNotCountable.php @@ -11,7 +11,7 @@ */ final class IsNotCountable extends Assertion { - public function __construct(public readonly readonly bool $is_negatable) + public function __construct(public readonly bool $is_negatable) { } diff --git a/src/Psalm/Storage/Assertion/NonEmptyCountable.php b/src/Psalm/Storage/Assertion/NonEmptyCountable.php index 3d45a4302cc..a36bffdd2a6 100644 --- a/src/Psalm/Storage/Assertion/NonEmptyCountable.php +++ b/src/Psalm/Storage/Assertion/NonEmptyCountable.php @@ -11,7 +11,7 @@ */ final class NonEmptyCountable extends Assertion { - public function __construct(public readonly readonly bool $is_negatable) + public function __construct(public readonly bool $is_negatable) { } diff --git a/src/Psalm/Storage/Assertion/NotInArray.php b/src/Psalm/Storage/Assertion/NotInArray.php index db79e877c4e..17c385f8825 100644 --- a/src/Psalm/Storage/Assertion/NotInArray.php +++ b/src/Psalm/Storage/Assertion/NotInArray.php @@ -13,7 +13,7 @@ final class NotInArray extends Assertion { public function __construct( - public readonly readonly Union $type, + public readonly Union $type, ) { } diff --git a/src/Psalm/Storage/AttributeArg.php b/src/Psalm/Storage/AttributeArg.php index edfd57acc1d..0a7c01136f6 100644 --- a/src/Psalm/Storage/AttributeArg.php +++ b/src/Psalm/Storage/AttributeArg.php @@ -17,9 +17,9 @@ final class AttributeArg use ImmutableNonCloneableTrait; public function __construct( - public ?string $name, - public Union|UnresolvedConstantComponent $type, - public CodeLocation $location, + public readonly ?string $name, + public readonly Union|UnresolvedConstantComponent $type, + public readonly CodeLocation $location, ) { } } diff --git a/src/Psalm/Storage/AttributeStorage.php b/src/Psalm/Storage/AttributeStorage.php index 3a7ff491a00..ad779ec05ff 100644 --- a/src/Psalm/Storage/AttributeStorage.php +++ b/src/Psalm/Storage/AttributeStorage.php @@ -18,10 +18,10 @@ final class AttributeStorage * @param list $args */ public function __construct( - public string $fq_class_name, - public array $args, - public CodeLocation $location, - public CodeLocation $name_location, + public readonly string $fq_class_name, + public readonly array $args, + public readonly CodeLocation $location, + public readonly CodeLocation $name_location, ) { } } diff --git a/src/Psalm/Storage/ClassConstantStorage.php b/src/Psalm/Storage/ClassConstantStorage.php index e7fe4e36700..9bdcdf17fd6 100644 --- a/src/Psalm/Storage/ClassConstantStorage.php +++ b/src/Psalm/Storage/ClassConstantStorage.php @@ -36,16 +36,16 @@ public function __construct( * The type inferred from the value. */ public ?Union $inferred_type, - public int $visibility, - public ?CodeLocation $location, - public ?CodeLocation $type_location = null, - public ?CodeLocation $stmt_location = null, - public bool $deprecated = false, - public bool $final = false, - public ?UnresolvedConstantComponent $unresolved_node = null, - public array $attributes = [], - public array $suppressed_issues = [], - public ?string $description = null, + public readonly int $visibility, + public readonly ?CodeLocation $location, + public readonly ?CodeLocation $type_location = null, + public readonly ?CodeLocation $stmt_location = null, + public readonly bool $deprecated = false, + public readonly bool $final = false, + public readonly ?UnresolvedConstantComponent $unresolved_node = null, + public readonly array $attributes = [], + public readonly array $suppressed_issues = [], + public readonly ?string $description = null, ) { } From b2bde470a733cf188192857c3a62e8050c0d6251 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 15:44:05 +0200 Subject: [PATCH 33/63] cs-fix --- src/Psalm/Internal/Analyzer/AttributesAnalyzer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Psalm/Internal/Analyzer/AttributesAnalyzer.php b/src/Psalm/Internal/Analyzer/AttributesAnalyzer.php index 5d1eaafd2bb..7ac69ca8a63 100644 --- a/src/Psalm/Internal/Analyzer/AttributesAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/AttributesAnalyzer.php @@ -25,11 +25,11 @@ use Psalm\Type\Atomic\TLiteralString; use Psalm\Type\Union; +use function array_key_first; use function array_shift; use function array_values; use function assert; use function count; -use function reset; use function strtolower; /** From 6613c928d22c9e2ebe290ca461cf142390dd9af0 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 15:52:52 +0200 Subject: [PATCH 34/63] Revert --- tests/TypeReconciliation/ReconcilerTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/TypeReconciliation/ReconcilerTest.php b/tests/TypeReconciliation/ReconcilerTest.php index 5c1b0a150f0..272029a6b8f 100644 --- a/tests/TypeReconciliation/ReconcilerTest.php +++ b/tests/TypeReconciliation/ReconcilerTest.php @@ -4,6 +4,7 @@ namespace Psalm\Tests\TypeReconciliation; +use Countable; use Psalm\Context; use Psalm\Internal\Analyzer\FileAnalyzer; use Psalm\Internal\Analyzer\StatementsAnalyzer; @@ -63,6 +64,7 @@ class A {} class B {} interface SomeInterface {} '); + $this->project_analyzer->getCodebase()->queueClassLikeForScanning(Countable::class); $this->project_analyzer->getCodebase()->scanFiles(); } From 64ef0d9666d54c1cd878c4eaee13e5bf67235ad5 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 18:44:02 +0200 Subject: [PATCH 35/63] cs-fix --- .../Scanner/UnresolvedConstant/ArrayOffsetFetch.php | 6 ++++-- .../Internal/Scanner/UnresolvedConstant/KeyValuePair.php | 6 ++++-- .../Scanner/UnresolvedConstant/UnresolvedBinaryOp.php | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php index e437117571d..c3b11b3061e 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php @@ -12,7 +12,9 @@ */ final class ArrayOffsetFetch extends UnresolvedConstantComponent { - public function __construct(public readonly UnresolvedConstantComponent $array, public readonly UnresolvedConstantComponent $offset) - { + public function __construct( + public readonly UnresolvedConstantComponent $array, + public readonly UnresolvedConstantComponent $offset, + ) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php index 34c3c9455b7..9cd222dc822 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php @@ -12,7 +12,9 @@ */ final class KeyValuePair extends UnresolvedConstantComponent { - public function __construct(public readonly ?UnresolvedConstantComponent $key, public readonly UnresolvedConstantComponent $value) - { + public function __construct( + public readonly ?UnresolvedConstantComponent $key, + public readonly UnresolvedConstantComponent $value, + ) { } } diff --git a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php index ad316011299..58bd8cb2f9f 100644 --- a/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php +++ b/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php @@ -15,7 +15,9 @@ abstract class UnresolvedBinaryOp extends UnresolvedConstantComponent { use ImmutableNonCloneableTrait; - public function __construct(public readonly UnresolvedConstantComponent $left, public readonly UnresolvedConstantComponent $right) - { + public function __construct( + public readonly UnresolvedConstantComponent $left, + public readonly UnresolvedConstantComponent $right, + ) { } } From b62fe449829b40c2694623bc526a14eec710b5a8 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 18:59:43 +0200 Subject: [PATCH 36/63] Fix --- UPGRADING.md | 8 ++++++++ .../scripts/update_signaturemap_from_other_tool.php | 2 +- examples/plugins/ClassUnqualifier.php | 2 +- src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php | 2 +- .../Analyzer/Statements/Block/ForeachAnalyzer.php | 2 +- .../Expression/Call/Method/AtomicMethodCallAnalyzer.php | 1 + .../Expression/Fetch/AtomicPropertyFetchAnalyzer.php | 3 ++- src/Psalm/Internal/Analyzer/StatementsAnalyzer.php | 2 +- .../FileManipulation/FunctionDocblockManipulator.php | 2 +- src/Psalm/Internal/LanguageServer/LanguageServer.php | 4 ++-- .../ReturnTypeProvider/ArrayMapReturnTypeProvider.php | 4 ++-- src/Psalm/Internal/Type/SimpleAssertionReconciler.php | 4 ++-- src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php | 1 + src/Psalm/Internal/Type/TypeParser.php | 3 +-- src/Psalm/IssueBuffer.php | 8 ++++---- src/Psalm/Report/ByIssueLevelAndTypeReport.php | 2 +- src/Psalm/Report/CountReport.php | 2 +- src/Psalm/Storage/FunctionLikeStorage.php | 4 ++-- src/Psalm/Type/Atomic/TValueOf.php | 6 +++--- 19 files changed, 36 insertions(+), 26 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 55cb4f65119..2bf88c584a4 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -44,6 +44,14 @@ - [BC] `Psalm\CodeLocation\Raw`, `Psalm\CodeLocation\ParseErrorLocation`, `Psalm\CodeLocation\DocblockTypeLocation`, `Psalm\Report\CountReport`, `Psalm\Type\Atomic\TNonEmptyArray` are now all final. +- [BC] `Psalm\Config` is now final. + +- [BC] The return type of `Psalm\Plugin\ArgTypeInferer::infer` changed from `Union|false` to `Union|null` + +- [BC] The `extra_types` property and `setIntersectionTypes` method of `Psalm\Type\Atomic\TTypeAlias` were removed. + +- [BC] Methods `convertSeverity` and `calculateFingerprint` of `Psalm\Report\CodeClimateReport` were removed. + # Upgrading from Psalm 4 to Psalm 5 ## Changed diff --git a/dictionaries/scripts/update_signaturemap_from_other_tool.php b/dictionaries/scripts/update_signaturemap_from_other_tool.php index 21fb61166d5..d50e88ee0a8 100644 --- a/dictionaries/scripts/update_signaturemap_from_other_tool.php +++ b/dictionaries/scripts/update_signaturemap_from_other_tool.php @@ -30,7 +30,7 @@ $removed_foreign_functions ); -uksort($new_local, fn($a, $b) => strtolower($a) <=> strtolower($b)); +uksort($new_local, static fn($a, $b) => strtolower($a) <=> strtolower($b)); foreach ($new_local as $name => $data) { if (!is_array($data)) { diff --git a/examples/plugins/ClassUnqualifier.php b/examples/plugins/ClassUnqualifier.php index d2b05332329..44104376292 100644 --- a/examples/plugins/ClassUnqualifier.php +++ b/examples/plugins/ClassUnqualifier.php @@ -44,7 +44,7 @@ public static function afterClassLikeExistenceCheck( $new_candidate_type = implode( '', array_map( - fn($f) => $f[0], + static fn($f) => $f[0], $type_tokens, ), ); diff --git a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php index 40a6f778b25..47e716f2225 100644 --- a/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php @@ -704,7 +704,7 @@ protected function checkTemplateParams( && $storage->template_types && $storage->template_covariants && ($local_offset - = array_search($t->param_name, array_keys($storage->template_types))) + = array_search($t->param_name, array_keys($storage->template_types), true)) !== false && !empty($storage->template_covariants[$local_offset]) ) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php index c11dba95c61..d71628cdfb9 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php @@ -1091,7 +1091,7 @@ private static function getExtendedType( ): ?Union { if ($calling_class === $template_class) { if (isset($class_template_types[$template_name]) && $calling_type_params) { - $offset = array_search($template_name, array_keys($class_template_types)); + $offset = array_search($template_name, array_keys($class_template_types), true); if ($offset !== false && isset($calling_type_params[$offset])) { return $calling_type_params[$offset]; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php index 74847d3861c..1e956a9039f 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php @@ -752,6 +752,7 @@ private static function handleTemplatedMixins( $param_position = array_search( $mixin->param_name, $template_type_keys, + true, ); if ($param_position !== false diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php index 9d55139838d..95d86401724 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php @@ -787,6 +787,7 @@ public static function localizePropertyType( $position = array_search( $param_name, array_keys($property_class_storage->template_types), + true, ); } @@ -999,7 +1000,7 @@ private static function handleEnumName( empty($relevant_enum_case_names) ? Type::getNonEmptyString() : new Union(array_map( - fn(string $name): TString => Type::getAtomicStringFromLiteral($name), + static fn(string $name): TString => Type::getAtomicStringFromLiteral($name), $relevant_enum_case_names, )), ); diff --git a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php index afa7a0beaab..e47bb93978e 100644 --- a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php @@ -865,7 +865,7 @@ public function checkUnreferencedVars(array $stmts, Context $context): void } if ($function_storage) { - $param_index = array_search(substr($var_id, 1), array_keys($function_storage->param_lookup)); + $param_index = array_search(substr($var_id, 1), array_keys($function_storage->param_lookup), true); if ($param_index !== false) { $param = $function_storage->params[$param_index]; diff --git a/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php b/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php index fe63e1e38aa..3004060d044 100644 --- a/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php +++ b/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php @@ -412,7 +412,7 @@ private function getDocblock(): string $modified_docblock = true; $inferredThrowsClause = array_reduce( $this->throwsExceptions, - fn(string $throwsClause, string $exception) => $throwsClause === '' + static fn(string $throwsClause, string $exception) => $throwsClause === '' ? $exception : $throwsClause.'|'.$exception, '', diff --git a/src/Psalm/Internal/LanguageServer/LanguageServer.php b/src/Psalm/Internal/LanguageServer/LanguageServer.php index df2f691cd68..9cf76e3f2c1 100644 --- a/src/Psalm/Internal/LanguageServer/LanguageServer.php +++ b/src/Psalm/Internal/LanguageServer/LanguageServer.php @@ -200,7 +200,7 @@ function (Message $msg): void { $this->protocolReader->on( 'readMessageGroup', - function (): void { + static function (): void { //$this->verboseLog('Received message group'); //$this->doAnalysis(); }, @@ -712,7 +712,7 @@ function (IssueData $issue_data): Diagnostic { return $diagnostic; }, array_filter( - array_map(function (IssueData $issue_data) use (&$issue_baseline) { + array_map(static function (IssueData $issue_data) use (&$issue_baseline) { if (empty($issue_baseline)) { return $issue_data; } diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php index 50f98b3af74..795615b983f 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php @@ -115,9 +115,9 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev $array_arg_types = array_map(null, ...$array_arg_types); $array_arg_types = array_map( /** @param non-empty-array $sub */ - function (array $sub) use ($null) { + static function (array $sub) use ($null) { $sub = array_map( - fn(?Union $t) => $t ?? $null, + static fn(?Union $t) => $t ?? $null, $sub, ); return new Union([new TKeyedArray($sub, null, null, true)]); diff --git a/src/Psalm/Internal/Type/SimpleAssertionReconciler.php b/src/Psalm/Internal/Type/SimpleAssertionReconciler.php index c748d3edcd0..6bbdc46a543 100644 --- a/src/Psalm/Internal/Type/SimpleAssertionReconciler.php +++ b/src/Psalm/Internal/Type/SimpleAssertionReconciler.php @@ -683,7 +683,7 @@ private static function reconcileNonEmptyCountable( $existing_var_type->removeType('array'); $existing_var_type->addType($array_atomic_type->setProperties( array_map( - fn(Union $union) => $union->setPossiblyUndefined(false), + static fn(Union $union) => $union->setPossiblyUndefined(false), $array_atomic_type->properties, ), )); @@ -803,7 +803,7 @@ private static function reconcileExactlyCountable( $existing_var_type->removeType('array'); $existing_var_type->addType($array_atomic_type->setProperties( array_map( - fn(Union $union) => $union->setPossiblyUndefined(false), + static fn(Union $union) => $union->setPossiblyUndefined(false), $array_atomic_type->properties, ), )); diff --git a/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php b/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php index fca39e97927..aa01a7ae93e 100644 --- a/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php +++ b/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php @@ -1333,6 +1333,7 @@ public static function getMappedGenericTypeParams( $old_params_offset = (int) array_search( $template->param_name, array_keys($input_class_storage->template_types), + true, ); $candidate_param_types[] = ($input_type_params[$old_params_offset] ?? Type::getMixed()) diff --git a/src/Psalm/Internal/Type/TypeParser.php b/src/Psalm/Internal/Type/TypeParser.php index f12029cafcb..4e1c737ab55 100644 --- a/src/Psalm/Internal/Type/TypeParser.php +++ b/src/Psalm/Internal/Type/TypeParser.php @@ -960,7 +960,7 @@ private static function getTypeFromGenericTree( } assert(count($parse_tree->children) === 2); - $get_int_range_bound = function (ParseTree $parse_tree, Union $generic_param, string $bound_name): ?int { + $get_int_range_bound = static function (ParseTree $parse_tree, Union $generic_param, string $bound_name): ?int { if (!$parse_tree instanceof Value || count($generic_param->getAtomicTypes()) > 1 || (!$generic_param->getSingleAtomic() instanceof TLiteralInt @@ -972,7 +972,6 @@ private static function getTypeFromGenericTree( "Invalid type \"{$generic_param->getId()}\" as int $bound_name boundary", ); } - $generic_param_atomic = $generic_param->getSingleAtomic(); return $generic_param_atomic instanceof TLiteralInt ? $generic_param_atomic->value : null; }; diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index 0f0eb5e6df2..1e3446ce104 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -187,7 +187,7 @@ public static function isSuppressed(CodeIssue $e, array $suppressed_issues = []) return true; } - $suppressed_issue_position = array_search($issue_type, $suppressed_issues); + $suppressed_issue_position = array_search($issue_type, $suppressed_issues, true); if ($suppressed_issue_position !== false) { if (is_int($suppressed_issue_position)) { @@ -200,7 +200,7 @@ public static function isSuppressed(CodeIssue $e, array $suppressed_issues = []) $parent_issue_type = Config::getParentIssueType($issue_type); if ($parent_issue_type) { - $suppressed_issue_position = array_search($parent_issue_type, $suppressed_issues); + $suppressed_issue_position = array_search($parent_issue_type, $suppressed_issues, true); if ($suppressed_issue_position !== false) { if (is_int($suppressed_issue_position)) { @@ -213,7 +213,7 @@ public static function isSuppressed(CodeIssue $e, array $suppressed_issues = []) $suppress_all_position = $config->disable_suppress_all ? false - : array_search('all', $suppressed_issues); + : array_search('all', $suppressed_issues, true); if ($suppress_all_position !== false) { if (is_int($suppress_all_position)) { @@ -950,7 +950,7 @@ public static function getOutput( return $output->create(); } - private static function alreadyEmitted(string $message): bool + public static function alreadyEmitted(string $message): bool { $sham = sha1($message); diff --git a/src/Psalm/Report/ByIssueLevelAndTypeReport.php b/src/Psalm/Report/ByIssueLevelAndTypeReport.php index 69445ce89e6..35f21b36dcc 100644 --- a/src/Psalm/Report/ByIssueLevelAndTypeReport.php +++ b/src/Psalm/Report/ByIssueLevelAndTypeReport.php @@ -182,7 +182,7 @@ private function sortIssuesByLevelAndType(): void { usort( $this->issues_data, - fn(IssueData $left, IssueData $right): int => [$left->error_level > 0, -$left->error_level, + static fn(IssueData $left, IssueData $right): int => [$left->error_level > 0, -$left->error_level, $left->type, $left->file_path, $left->file_name, $left->line_from] <=> [$right->error_level > 0, -$right->error_level, $right->type, $right->file_path, $right->file_name, $right->line_from], diff --git a/src/Psalm/Report/CountReport.php b/src/Psalm/Report/CountReport.php index a0ec59602ba..eb47b4c884b 100644 --- a/src/Psalm/Report/CountReport.php +++ b/src/Psalm/Report/CountReport.php @@ -21,7 +21,7 @@ public function create(): string $issue_type_counts[$issue_data->type] = 1; } } - uksort($issue_type_counts, function (string $a, string $b) use ($issue_type_counts): int { + uksort($issue_type_counts, static function (string $a, string $b) use ($issue_type_counts): int { $cmp_result = $issue_type_counts[$a] <=> $issue_type_counts[$b]; if ($cmp_result === 0) { return $a <=> $b; diff --git a/src/Psalm/Storage/FunctionLikeStorage.php b/src/Psalm/Storage/FunctionLikeStorage.php index 5fd48feb486..b3880b5b982 100644 --- a/src/Psalm/Storage/FunctionLikeStorage.php +++ b/src/Psalm/Storage/FunctionLikeStorage.php @@ -196,7 +196,7 @@ public function getHoverMarkdown(): string $params = count($this->params) > 0 ? "\n" . implode( ",\n", array_map( - function (FunctionLikeParameter $param): string { + static function (FunctionLikeParameter $param): string { $realType = $param->type ?: 'mixed'; return " {$realType} \${$param->name}"; }, @@ -224,7 +224,7 @@ public function getCompletionSignature(): string $symbol_text = 'function ' . $this->cased_name . '(' . implode( ',', array_map( - fn(FunctionLikeParameter $param): string => ($param->type ?: 'mixed') . ' $' . $param->name, + static fn(FunctionLikeParameter $param): string => ($param->type ?: 'mixed') . ' $' . $param->name, $this->params, ), ) . ') : ' . ($this->return_type ?: 'mixed'); diff --git a/src/Psalm/Type/Atomic/TValueOf.php b/src/Psalm/Type/Atomic/TValueOf.php index 71afca107e3..38e09570959 100644 --- a/src/Psalm/Type/Atomic/TValueOf.php +++ b/src/Psalm/Type/Atomic/TValueOf.php @@ -39,9 +39,9 @@ private static function getValueTypeForNamedObject(array $cases, TNamedObject $a } return new Union(array_map( - function (EnumCaseStorage $case): Atomic { - assert($case->value !== null); // Backed enum must have a value - + static function (EnumCaseStorage $case): Atomic { + assert($case->value !== null); + // Backed enum must have a value return $case->value; }, array_values($cases), From 46ae91e6c179c8b1c2db72281627e48b4af08e19 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 19:02:17 +0200 Subject: [PATCH 37/63] Fix --- tests/AsyncTestCase.php | 2 +- tests/CodebaseTest.php | 2 +- tests/Config/ConfigTest.php | 2 +- .../Plugin/Hook/CustomArrayMapFunctionStorageProvider.php | 3 +-- tests/DocumentationTest.php | 2 +- tests/FileDiffTest.php | 4 ++-- tests/TaintTest.php | 2 +- tests/TestCase.php | 2 +- tests/TypeComparatorTest.php | 2 +- tests/fixtures/DestructiveAutoloader/autoloader.php | 2 +- tests/fixtures/SuicidalAutoloader/autoloader.php | 4 +--- 11 files changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/AsyncTestCase.php b/tests/AsyncTestCase.php index 0e89d76594e..09c0eb81037 100644 --- a/tests/AsyncTestCase.php +++ b/tests/AsyncTestCase.php @@ -154,7 +154,7 @@ public static function assertArrayKeysAreStrings(array $array, string $message = */ public static function assertArrayKeysAreZeroOrString(array $array, string $message = ''): void { - $isZeroOrString = /** @param mixed $key */ fn($key): bool => $key === 0 || is_string($key); + $isZeroOrString = /** @param mixed $key */ static fn($key): bool => $key === 0 || is_string($key); $validKeys = array_filter($array, $isZeroOrString, ARRAY_FILTER_USE_KEY); self::assertTrue(count($array) === count($validKeys), $message); } diff --git a/tests/CodebaseTest.php b/tests/CodebaseTest.php index 0a176430798..d10d9201411 100644 --- a/tests/CodebaseTest.php +++ b/tests/CodebaseTest.php @@ -161,7 +161,7 @@ public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event) ? (string)$stmt->extends->getAttribute('resolvedName') : ''; $storage->custom_metadata['implements'] = array_map( - fn(Name $aspect): string => (string)$aspect->getAttribute('resolvedName'), + static fn(Name $aspect): string => (string)$aspect->getAttribute('resolvedName'), $stmt->implements, ); $storage->custom_metadata['a'] = 'b'; diff --git a/tests/Config/ConfigTest.php b/tests/Config/ConfigTest.php index 9fa8042c55c..34a5b06f976 100644 --- a/tests/Config/ConfigTest.php +++ b/tests/Config/ConfigTest.php @@ -1108,7 +1108,7 @@ public function testAllPossibleIssues(): void * @param string $issue_name * @return string */ - fn($issue_name): string => '<' . $issue_name . ' errorLevel="suppress" />' . "\n", + static fn($issue_name): string => '<' . $issue_name . ' errorLevel="suppress" />' . "\n", IssueHandler::getAllIssueTypes(), ), ); diff --git a/tests/Config/Plugin/Hook/CustomArrayMapFunctionStorageProvider.php b/tests/Config/Plugin/Hook/CustomArrayMapFunctionStorageProvider.php index fb2853f3530..cb3284754f8 100644 --- a/tests/Config/Plugin/Hook/CustomArrayMapFunctionStorageProvider.php +++ b/tests/Config/Plugin/Hook/CustomArrayMapFunctionStorageProvider.php @@ -56,11 +56,10 @@ public static function getFunctionStorage(DynamicFunctionStorageProviderEvent $e $custom_array_map_storage->return_type = self::createReturnType($all_expected_callables); $custom_array_map_storage->params = [ ...array_map( - function (TCallable $expected, int $offset) { + static function (TCallable $expected, int $offset) { $t = new Union([$expected]); $param = new FunctionLikeParameter('fn' . $offset, false, $t, $t); $param->is_optional = false; - return $param; }, $all_expected_callables, diff --git a/tests/DocumentationTest.php b/tests/DocumentationTest.php index 9768eecfa83..d86293a8241 100644 --- a/tests/DocumentationTest.php +++ b/tests/DocumentationTest.php @@ -348,7 +348,7 @@ public function testShortcodesAreUnique(): void $duplicate_shortcodes = array_filter( $all_shortcodes, - fn($issues): bool => count($issues) > 1 + static fn($issues): bool => count($issues) > 1 ); $this->assertEquals( diff --git a/tests/FileDiffTest.php b/tests/FileDiffTest.php index 0e7982552b9..2e206537b7b 100644 --- a/tests/FileDiffTest.php +++ b/tests/FileDiffTest.php @@ -64,7 +64,7 @@ public function testCode( * @param array{0: int, 1: int, 2: int, 3: int} $arr * @return array{0: int, 1: int} */ - fn(array $arr): array => [$arr[2], $arr[3]], + static fn(array $arr): array => [$arr[2], $arr[3]], $diff[3], ); @@ -135,7 +135,7 @@ public function testPartialAstDiff( * @param array{0: int, 1: int, 2: int, 3: int} $arr * @return array{0: int, 1: int} */ - fn(array $arr): array => [$arr[2], $arr[3]], + static fn(array $arr): array => [$arr[2], $arr[3]], $diff[3], ); diff --git a/tests/TaintTest.php b/tests/TaintTest.php index f83d45bae19..4e7c2bda417 100644 --- a/tests/TaintTest.php +++ b/tests/TaintTest.php @@ -2602,7 +2602,7 @@ public function multipleTaintIssuesAreDetected(string $code, array $expectedIssu $this->analyzeFile($filePath, new Context(), false); $actualIssueTypes = array_map( - fn(IssueData $issue): string => $issue->type . '{ ' . trim($issue->snippet) . ' }', + static fn(IssueData $issue): string => $issue->type . '{ ' . trim($issue->snippet) . ' }', IssueBuffer::getIssuesDataForFile($filePath), ); self::assertSame($expectedIssuesTypes, $actualIssueTypes); diff --git a/tests/TestCase.php b/tests/TestCase.php index 8e61664f870..5ddeebd3bfd 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -151,7 +151,7 @@ public static function assertArrayKeysAreStrings(array $array, string $message = public static function assertArrayKeysAreZeroOrString(array $array, string $message = ''): void { - $isZeroOrString = /** @param mixed $key */ fn($key): bool => $key === 0 || is_string($key); + $isZeroOrString = /** @param mixed $key */ static fn($key): bool => $key === 0 || is_string($key); $validKeys = array_filter($array, $isZeroOrString, ARRAY_FILTER_USE_KEY); self::assertTrue(count($array) === count($validKeys), $message); } diff --git a/tests/TypeComparatorTest.php b/tests/TypeComparatorTest.php index 434a1f30456..00ad55bea49 100644 --- a/tests/TypeComparatorTest.php +++ b/tests/TypeComparatorTest.php @@ -90,7 +90,7 @@ public function getAllBasicTypes(): array $basic_types['list{123}'] = true; return array_map( - fn($type) => [$type], + static fn($type) => [$type], array_keys($basic_types), ); } diff --git a/tests/fixtures/DestructiveAutoloader/autoloader.php b/tests/fixtures/DestructiveAutoloader/autoloader.php index 17cb0a152c5..37a8624de36 100644 --- a/tests/fixtures/DestructiveAutoloader/autoloader.php +++ b/tests/fixtures/DestructiveAutoloader/autoloader.php @@ -9,7 +9,7 @@ $GLOBALS[$key] = new Exception; } -spl_autoload_register(function() { +spl_autoload_register(static function () { // and destroy vars again // this will run during scanning (?) foreach ($GLOBALS as $key => $_) { diff --git a/tests/fixtures/SuicidalAutoloader/autoloader.php b/tests/fixtures/SuicidalAutoloader/autoloader.php index 365fa7b723e..d506219c141 100644 --- a/tests/fixtures/SuicidalAutoloader/autoloader.php +++ b/tests/fixtures/SuicidalAutoloader/autoloader.php @@ -3,7 +3,7 @@ use React\Promise\PromiseInterface as ReactPromise; use Composer\InstalledVersions; -spl_autoload_register(function (string $className) { +spl_autoload_register(static function (string $className) { $knownBadClasses = [ ReactPromise::class, // amphp/amp ResourceBundle::class, // symfony/polyfill-php73 @@ -25,11 +25,9 @@ 'Symfony\Component\String\s', 'Symfony\Component\Translation\t', ]; - if (in_array($className, $knownBadClasses)) { return; } - $ex = new RuntimeException('Attempted to load ' . $className); echo $ex->__toString() . "\n\n" . $ex->getTraceAsString() . "\n\n"; exit(70); From 17b70c5ae5391c94cec7bd73dd9a520c52fa801c Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 19:05:04 +0200 Subject: [PATCH 38/63] Fixes --- tests/ReportOutputTest.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/ReportOutputTest.php b/tests/ReportOutputTest.php index bee44b19d37..c17370a8106 100644 --- a/tests/ReportOutputTest.php +++ b/tests/ReportOutputTest.php @@ -712,6 +712,7 @@ public function testJsonReport(): void $issue_data = [ [ + 'link' => 'https://psalm.dev/024', 'severity' => 'error', 'line_from' => 3, 'line_to' => 3, @@ -727,13 +728,13 @@ public function testJsonReport(): void 'snippet_to' => 83, 'column_from' => 10, 'column_to' => 26, - 'error_level' => -1, 'shortcode' => 24, - 'link' => 'https://psalm.dev/024', + 'error_level' => -1, 'taint_trace' => null, 'other_references' => null, ], [ + 'link' => 'https://psalm.dev/138', 'severity' => 'error', 'line_from' => 3, 'line_to' => 3, @@ -749,13 +750,13 @@ public function testJsonReport(): void 'snippet_to' => 83, 'column_from' => 10, 'column_to' => 26, - 'error_level' => 1, 'shortcode' => 138, - 'link' => 'https://psalm.dev/138', + 'error_level' => 1, 'taint_trace' => null, 'other_references' => null, ], [ + 'link' => 'https://psalm.dev/047', 'severity' => 'error', 'line_from' => 2, 'line_to' => 2, @@ -771,13 +772,13 @@ public function testJsonReport(): void 'snippet_to' => 56, 'column_from' => 42, 'column_to' => 49, - 'error_level' => 1, 'shortcode' => 47, - 'link' => 'https://psalm.dev/047', + 'error_level' => 1, 'taint_trace' => null, 'other_references' => null, ], [ + 'link' => 'https://psalm.dev/020', 'severity' => 'error', 'line_from' => 8, 'line_to' => 8, @@ -793,13 +794,13 @@ public function testJsonReport(): void 'snippet_to' => 172, 'column_from' => 6, 'column_to' => 15, - 'error_level' => -1, 'shortcode' => 20, - 'link' => 'https://psalm.dev/020', + 'error_level' => -1, 'taint_trace' => null, 'other_references' => null, ], [ + 'link' => 'https://psalm.dev/126', 'severity' => 'info', 'line_from' => 17, 'line_to' => 17, @@ -815,9 +816,8 @@ public function testJsonReport(): void 'snippet_to' => 277, 'column_from' => 6, 'column_to' => 8, - 'error_level' => 3, 'shortcode' => 126, - 'link' => 'https://psalm.dev/126', + 'error_level' => 3, 'taint_trace' => null, 'other_references' => null, ], From 90dea2f9479b8b84563c7e1d462d97c5da6d8964 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 19:06:16 +0200 Subject: [PATCH 39/63] Fix --- tests/EnumTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 35df957b6b3..ebc67a05e1e 100644 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -633,6 +633,9 @@ function noop(string $s): string noop($foo); noop(FooEnum::Foo->value); PHP, + 'assertions' => [], + 'ignored_issues' => [], + 'php_version' => '8.1', ], 'backedEnumCaseValueFromClassConstant' => [ 'code' => <<<'PHP' From dc2b7245b2aeafe8e8023a16d5b2bb5ade0cb2fd Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 21 Oct 2023 19:10:09 +0200 Subject: [PATCH 40/63] cs-fix --- src/Psalm/Internal/Type/TypeParser.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Psalm/Internal/Type/TypeParser.php b/src/Psalm/Internal/Type/TypeParser.php index 4e1c737ab55..da20ad4cc55 100644 --- a/src/Psalm/Internal/Type/TypeParser.php +++ b/src/Psalm/Internal/Type/TypeParser.php @@ -960,7 +960,11 @@ private static function getTypeFromGenericTree( } assert(count($parse_tree->children) === 2); - $get_int_range_bound = static function (ParseTree $parse_tree, Union $generic_param, string $bound_name): ?int { + $get_int_range_bound = static function ( + ParseTree $parse_tree, + Union $generic_param, + string $bound_name, + ): ?int { if (!$parse_tree instanceof Value || count($generic_param->getAtomicTypes()) > 1 || (!$generic_param->getSingleAtomic() instanceof TLiteralInt From fa97e6ddf53683182aea20971f6e745838289f5b Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sun, 22 Oct 2023 21:26:19 +0200 Subject: [PATCH 41/63] Fix --- .../Internal/FileManipulation/FunctionDocblockManipulator.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php b/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php index 091e13a3e14..3004060d044 100644 --- a/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php +++ b/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php @@ -45,7 +45,6 @@ final class FunctionDocblockManipulator private static array $manipulators = []; private readonly int $docblock_start; - private Closure|Function_|ClassMethod|ArrowFunction $stmt; private readonly int $docblock_end; From a88bf62c30fdcf78ddc5c197cd921616a7f0753e Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 29 Nov 2023 12:24:48 +0100 Subject: [PATCH 42/63] Tweak config --- src/Psalm/Internal/Fork/PsalmRestarter.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Psalm/Internal/Fork/PsalmRestarter.php b/src/Psalm/Internal/Fork/PsalmRestarter.php index 9332cdaab75..e25f5627e78 100644 --- a/src/Psalm/Internal/Fork/PsalmRestarter.php +++ b/src/Psalm/Internal/Fork/PsalmRestarter.php @@ -31,12 +31,12 @@ final class PsalmRestarter extends XdebugHandler 'jit' => 1205, 'validate_timestamps' => 0, 'file_update_protection' => 0, - 'jit_buffer_size' => 512 * 1024 * 1024, + 'jit_buffer_size' => 128 * 1024 * 1024, 'max_accelerated_files' => 1_000_000, 'interned_strings_buffer' => 64, - 'jit_max_root_traces' => 30_000_000, - 'jit_max_side_traces' => 30_000_000, - 'jit_max_exit_counters' => 30_000_000, + 'jit_max_root_traces' => 1_000_000, + 'jit_max_side_traces' => 1_000_000, + 'jit_max_exit_counters' => 1_000_000, 'jit_hot_loop' => 1, 'jit_hot_func' => 1, 'jit_hot_return' => 1, From d5b713e4391e6339bd0c69f664ae15c3ccd96e01 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Mon, 18 Dec 2023 14:51:53 +0100 Subject: [PATCH 43/63] Fix https://github.com/vimeo/psalm/issues/10501 - report error for non-strict comparison on truthy+falsy union --- .../Block/IfConditionalAnalyzer.php | 33 +++++++ .../Expression/BooleanNotAnalyzer.php | 35 ++++++++ tests/TypeReconciliation/ConditionalTest.php | 86 +++++++++++++++++++ 3 files changed, 154 insertions(+) diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php index a306cca4ca0..8db97e794a3 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php @@ -17,6 +17,7 @@ use Psalm\Issue\RedundantConditionGivenDocblockType; use Psalm\Issue\TypeDoesNotContainType; use Psalm\IssueBuffer; +use Psalm\Type\Atomic\TBool; use Psalm\Type\Reconciler; use function array_diff_key; @@ -366,6 +367,38 @@ public static function handleParadoxicalCondition( $statements_analyzer->getSuppressedIssues(), ); } + } elseif (!($stmt instanceof PhpParser\Node\Expr\BinaryOp\NotIdentical) + && !($stmt instanceof PhpParser\Node\Expr\BinaryOp\Identical) + && !($stmt instanceof PhpParser\Node\Expr\BooleanNot)) { + $has_both = false; + $both_types = $type->getBuilder(); + if (count($type->getAtomicTypes()) > 1) { + foreach ($both_types->getAtomicTypes() as $key => $atomic_type) { + if ($atomic_type->isTruthy() + || $atomic_type->isFalsy() + || $atomic_type instanceof TBool) { + $both_types->removeType($key); + continue; + } + + $has_both = true; + } + } + + if ($has_both) { + $both_types = $both_types->freeze(); + IssueBuffer::maybeAdd( + new TypeDoesNotContainType( + 'Operand of type ' . $type->getId() . ' contains ' . + 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . + $both_types->getId() . ', which can be falsy and truthy. ' . + 'This can cause possibly unexpected behavior. Use strict comparison instead.', + new CodeLocation($statements_analyzer, $stmt), + $type->getId() . ' truthy-falsy', + ), + $statements_analyzer->getSuppressedIssues(), + ); + } } } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php index 3c75dd9efca..bfe8d209e02 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php @@ -3,15 +3,20 @@ namespace Psalm\Internal\Analyzer\Statements\Expression; use PhpParser; +use Psalm\CodeLocation; use Psalm\Context; use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer; use Psalm\Internal\Analyzer\StatementsAnalyzer; +use Psalm\Issue\TypeDoesNotContainType; +use Psalm\IssueBuffer; use Psalm\Type; use Psalm\Type\Atomic\TBool; use Psalm\Type\Atomic\TFalse; use Psalm\Type\Atomic\TTrue; use Psalm\Type\Union; +use function count; + /** * @internal */ @@ -40,6 +45,36 @@ public static function analyze( } elseif ($expr_type->isAlwaysFalsy()) { $stmt_type = new TTrue($expr_type->from_docblock); } else { + $has_both = false; + $both_types = $expr_type->getBuilder(); + if (count($expr_type->getAtomicTypes()) > 1) { + foreach ($both_types->getAtomicTypes() as $key => $atomic_type) { + if ($atomic_type->isTruthy() + || $atomic_type->isFalsy() + || $atomic_type instanceof TBool) { + $both_types->removeType($key); + continue; + } + + $has_both = true; + } + } + + if ($has_both) { + $both_types = $both_types->freeze(); + IssueBuffer::maybeAdd( + new TypeDoesNotContainType( + 'Operand of type ' . $expr_type->getId() . ' contains ' . + 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . + $both_types->getId() . ', which can be falsy and truthy. ' . + 'This can cause possibly unexpected behavior. Use strict comparison instead.', + new CodeLocation($statements_analyzer, $stmt), + $expr_type->getId() . ' truthy-falsy', + ), + $statements_analyzer->getSuppressedIssues(), + ); + } + $stmt_type = new TBool(); } diff --git a/tests/TypeReconciliation/ConditionalTest.php b/tests/TypeReconciliation/ConditionalTest.php index 700ba17c621..bb16a20043e 100644 --- a/tests/TypeReconciliation/ConditionalTest.php +++ b/tests/TypeReconciliation/ConditionalTest.php @@ -38,6 +38,32 @@ function foo($a): void { if ($b === $a) { } }', ], + 'nonStrictConditionTruthyFalsyNoOverlap' => [ + 'code' => ' [ 'code' => ' 'TypeDoesNotContainType', ], + 'nonStrictConditionTruthyFalsy' => [ + 'code' => ' 'TypeDoesNotContainType', + ], + 'nonStrictConditionTruthyFalsyNegated' => [ + 'code' => ' 'TypeDoesNotContainType', + ], + 'nonStrictConditionTruthyFalsyFuncCall' => [ + 'code' => ' 'TypeDoesNotContainType', + ], + 'nonStrictConditionTruthyFalsyFuncCallNegated' => [ + 'code' => ' 'TypeDoesNotContainType', + ], 'redundantConditionForNonEmptyString' => [ 'code' => ' Date: Fri, 12 Jan 2024 22:40:47 +0100 Subject: [PATCH 44/63] add the fix for empty() too and fix empty returning bool on true/false only cases hiding errors when functions called --- .../Statements/Expression/EmptyAnalyzer.php | 82 +++++++++++++++---- tests/TypeReconciliation/EmptyTest.php | 32 ++++++++ 2 files changed, 100 insertions(+), 14 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php index 3b9014f85b4..40bf489ea5e 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php @@ -8,8 +8,15 @@ use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Issue\ForbiddenCode; use Psalm\Issue\InvalidArgument; +use Psalm\Issue\TypeDoesNotContainType; use Psalm\IssueBuffer; use Psalm\Type; +use Psalm\Type\Atomic\TBool; +use Psalm\Type\Atomic\TFalse; +use Psalm\Type\Atomic\TTrue; +use Psalm\Type\Union; + +use function count; /** * @internal @@ -35,21 +42,68 @@ public static function analyze( ); } - if (($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr)) - && $stmt_expr_type->hasBool() - && $stmt_expr_type->isSingle() - && !$stmt_expr_type->from_docblock - ) { - IssueBuffer::maybeAdd( - new InvalidArgument( - 'Calling empty on a boolean value is almost certainly unintended', - new CodeLocation($statements_analyzer->getSource(), $stmt->expr), - 'empty', - ), - $statements_analyzer->getSuppressedIssues(), - ); + $expr_type = $statements_analyzer->node_data->getType($stmt->expr); + + if ($expr_type) { + if ($expr_type->hasBool() + && $expr_type->isSingle() + && !$expr_type->from_docblock + ) { + IssueBuffer::maybeAdd( + new InvalidArgument( + 'Calling empty on a boolean value is almost certainly unintended', + new CodeLocation($statements_analyzer->getSource(), $stmt->expr), + 'empty', + ), + $statements_analyzer->getSuppressedIssues(), + ); + } + + if ($expr_type->isAlwaysTruthy() && $expr_type->possibly_undefined === false) { + $stmt_type = new TFalse($expr_type->from_docblock); + } elseif ($expr_type->isAlwaysFalsy()) { + $stmt_type = new TTrue($expr_type->from_docblock); + } else { + $has_both = false; + $both_types = $expr_type->getBuilder(); + if (count($expr_type->getAtomicTypes()) > 1) { + foreach ($both_types->getAtomicTypes() as $key => $atomic_type) { + if ($atomic_type->isTruthy() + || $atomic_type->isFalsy() + || $atomic_type instanceof TBool) { + $both_types->removeType($key); + continue; + } + + $has_both = true; + } + } + + if ($has_both) { + $both_types = $both_types->freeze(); + IssueBuffer::maybeAdd( + new TypeDoesNotContainType( + 'Operand of type ' . $expr_type->getId() . ' contains ' . + 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . + $both_types->getId() . ', which can be falsy and truthy. ' . + 'This can cause possibly unexpected behavior. Use strict comparison instead.', + new CodeLocation($statements_analyzer, $stmt), + $expr_type->getId() . ' truthy-falsy', + ), + $statements_analyzer->getSuppressedIssues(), + ); + } + + $stmt_type = new TBool(); + } + + $stmt_type = new Union([$stmt_type], [ + 'parent_nodes' => $expr_type->parent_nodes, + ]); + } else { + $stmt_type = Type::getBool(); } - $statements_analyzer->node_data->setType($stmt, Type::getBool()); + $statements_analyzer->node_data->setType($stmt, $stmt_type); } } diff --git a/tests/TypeReconciliation/EmptyTest.php b/tests/TypeReconciliation/EmptyTest.php index c7991804454..944ae2218b6 100644 --- a/tests/TypeReconciliation/EmptyTest.php +++ b/tests/TypeReconciliation/EmptyTest.php @@ -612,6 +612,14 @@ function test(string $s): void { '$GLOBALS[\'sql_query\']===' => 'string', ], ], + 'emptyLiteralTrueFalse' => [ + 'code' => ' [ + '$x===' => 'true', + ], + ], ]; } @@ -720,6 +728,30 @@ function nonEmptyString(string $str): string { }', 'error_message' => 'LessSpecificReturnStatement', ], + 'impossibleEmptyOnFalsyFunctionCall' => [ + 'code' => ' 'DocblockTypeContradiction', + ], + 'redundantEmptyOnFalsyFunctionCall' => [ + 'code' => ' 'RedundantConditionGivenDocblockType', + ], ]; } } From fb93aede1279db1a34c6477a1d5aa56a99bcbfa4 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:52:26 +0100 Subject: [PATCH 45/63] create a separate issue type --- config.xsd | 1 + docs/running_psalm/error_levels.md | 1 + docs/running_psalm/issues.md | 1 + .../issues/RiskyTruthyFalsyComparison.md | 29 +++++++++++++++++++ .../Block/IfConditionalAnalyzer.php | 5 ++-- .../Expression/BooleanNotAnalyzer.php | 6 ++-- .../Statements/Expression/EmptyAnalyzer.php | 6 ++-- .../Issue/RiskyTruthyFalsyComparison.php | 17 +++++++++++ tests/TypeReconciliation/ConditionalTest.php | 8 ++--- 9 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 docs/running_psalm/issues/RiskyTruthyFalsyComparison.md create mode 100644 src/Psalm/Issue/RiskyTruthyFalsyComparison.php diff --git a/config.xsd b/config.xsd index 5c176821e24..0f3e88916c8 100644 --- a/config.xsd +++ b/config.xsd @@ -427,6 +427,7 @@ + diff --git a/docs/running_psalm/error_levels.md b/docs/running_psalm/error_levels.md index 55a18b8fa61..df53f5227f6 100644 --- a/docs/running_psalm/error_levels.md +++ b/docs/running_psalm/error_levels.md @@ -173,6 +173,7 @@ Level 5 and above allows a more non-verifiable code, and higher levels are even - [TooManyArguments](issues/TooManyArguments.md) - [TypeDoesNotContainNull](issues/TypeDoesNotContainNull.md) - [TypeDoesNotContainType](issues/TypeDoesNotContainType.md) +- [RiskyTruthyFalsyComparison](issues/RiskyTruthyFalsyComparison.md) - [UndefinedMagicMethod](issues/UndefinedMagicMethod.md) - [UndefinedMagicPropertyAssignment](issues/UndefinedMagicPropertyAssignment.md) - [UndefinedMagicPropertyFetch](issues/UndefinedMagicPropertyFetch.md) diff --git a/docs/running_psalm/issues.md b/docs/running_psalm/issues.md index ac8135c7142..179f9bf7b53 100644 --- a/docs/running_psalm/issues.md +++ b/docs/running_psalm/issues.md @@ -229,6 +229,7 @@ - [ReferenceReusedFromConfusingScope](issues/ReferenceReusedFromConfusingScope.md) - [ReservedWord](issues/ReservedWord.md) - [RiskyCast](issues/RiskyCast.md) + - [RiskyTruthyFalsyComparison](issues/RiskyTruthyFalsyComparison.md) - [StringIncrement](issues/StringIncrement.md) - [TaintedCallable](issues/TaintedCallable.md) - [TaintedCookie](issues/TaintedCookie.md) diff --git a/docs/running_psalm/issues/RiskyTruthyFalsyComparison.md b/docs/running_psalm/issues/RiskyTruthyFalsyComparison.md new file mode 100644 index 00000000000..8d60969633e --- /dev/null +++ b/docs/running_psalm/issues/RiskyTruthyFalsyComparison.md @@ -0,0 +1,29 @@ +# RiskyTruthyFalsyComparison + +Emitted when comparing a value with multiple types that can both contain truthy and falsy values. + +```php +freeze(); IssueBuffer::maybeAdd( - new TypeDoesNotContainType( + new RiskyTruthyFalsyComparison( 'Operand of type ' . $type->getId() . ' contains ' . 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . $both_types->getId() . ', which can be falsy and truthy. ' . 'This can cause possibly unexpected behavior. Use strict comparison instead.', new CodeLocation($statements_analyzer, $stmt), - $type->getId() . ' truthy-falsy', + $type->getId(), ), $statements_analyzer->getSuppressedIssues(), ); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php index bfe8d209e02..71f6e19324f 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php @@ -7,7 +7,7 @@ use Psalm\Context; use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer; use Psalm\Internal\Analyzer\StatementsAnalyzer; -use Psalm\Issue\TypeDoesNotContainType; +use Psalm\Issue\RiskyTruthyFalsyComparison; use Psalm\IssueBuffer; use Psalm\Type; use Psalm\Type\Atomic\TBool; @@ -63,13 +63,13 @@ public static function analyze( if ($has_both) { $both_types = $both_types->freeze(); IssueBuffer::maybeAdd( - new TypeDoesNotContainType( + new RiskyTruthyFalsyComparison( 'Operand of type ' . $expr_type->getId() . ' contains ' . 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . $both_types->getId() . ', which can be falsy and truthy. ' . 'This can cause possibly unexpected behavior. Use strict comparison instead.', new CodeLocation($statements_analyzer, $stmt), - $expr_type->getId() . ' truthy-falsy', + $expr_type->getId(), ), $statements_analyzer->getSuppressedIssues(), ); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php index 40bf489ea5e..02fae12fd44 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php @@ -8,7 +8,7 @@ use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Issue\ForbiddenCode; use Psalm\Issue\InvalidArgument; -use Psalm\Issue\TypeDoesNotContainType; +use Psalm\Issue\RiskyTruthyFalsyComparison; use Psalm\IssueBuffer; use Psalm\Type; use Psalm\Type\Atomic\TBool; @@ -82,13 +82,13 @@ public static function analyze( if ($has_both) { $both_types = $both_types->freeze(); IssueBuffer::maybeAdd( - new TypeDoesNotContainType( + new RiskyTruthyFalsyComparison( 'Operand of type ' . $expr_type->getId() . ' contains ' . 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . $both_types->getId() . ', which can be falsy and truthy. ' . 'This can cause possibly unexpected behavior. Use strict comparison instead.', new CodeLocation($statements_analyzer, $stmt), - $expr_type->getId() . ' truthy-falsy', + $expr_type->getId(), ), $statements_analyzer->getSuppressedIssues(), ); diff --git a/src/Psalm/Issue/RiskyTruthyFalsyComparison.php b/src/Psalm/Issue/RiskyTruthyFalsyComparison.php new file mode 100644 index 00000000000..9150aa30b8c --- /dev/null +++ b/src/Psalm/Issue/RiskyTruthyFalsyComparison.php @@ -0,0 +1,17 @@ +dupe_key = $dupe_key; + } +} diff --git a/tests/TypeReconciliation/ConditionalTest.php b/tests/TypeReconciliation/ConditionalTest.php index bb16a20043e..2209c2f163d 100644 --- a/tests/TypeReconciliation/ConditionalTest.php +++ b/tests/TypeReconciliation/ConditionalTest.php @@ -3528,7 +3528,7 @@ function foo($arg) { if ($arg) { } }', - 'error_message' => 'TypeDoesNotContainType', + 'error_message' => 'RiskyTruthyFalsyComparison', ], 'nonStrictConditionTruthyFalsyNegated' => [ 'code' => ' 'TypeDoesNotContainType', + 'error_message' => 'RiskyTruthyFalsyComparison', ], 'nonStrictConditionTruthyFalsyFuncCall' => [ 'code' => ' 'TypeDoesNotContainType', + 'error_message' => 'RiskyTruthyFalsyComparison', ], 'nonStrictConditionTruthyFalsyFuncCallNegated' => [ 'code' => ' 'TypeDoesNotContainType', + 'error_message' => 'RiskyTruthyFalsyComparison', ], 'redundantConditionForNonEmptyString' => [ 'code' => ' Date: Sat, 13 Jan 2024 00:53:32 +0100 Subject: [PATCH 46/63] fix shepherd issue --- src/Psalm/PluginFileExtensionsSocket.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Psalm/PluginFileExtensionsSocket.php b/src/Psalm/PluginFileExtensionsSocket.php index 1e698e89cc5..0b5ac1333fa 100644 --- a/src/Psalm/PluginFileExtensionsSocket.php +++ b/src/Psalm/PluginFileExtensionsSocket.php @@ -55,8 +55,8 @@ public function addFileTypeScanner(string $fileExtension, string $className): vo 1_622_727_271, ); } - if (!empty($this->config->getFiletypeScanners()[$fileExtension]) - || !empty($this->additionalFileTypeScanners[$fileExtension]) + if (isset($this->config->getFiletypeScanners()[$fileExtension]) + || isset($this->additionalFileTypeScanners[$fileExtension]) ) { throw new LogicException( sprintf('Cannot redeclare scanner for file-type %s', $fileExtension), @@ -91,8 +91,8 @@ public function addFileTypeAnalyzer(string $fileExtension, string $className): v 1_622_727_281, ); } - if (!empty($this->config->getFiletypeAnalyzers()[$fileExtension]) - || !empty($this->additionalFileTypeAnalyzers[$fileExtension]) + if (isset($this->config->getFiletypeAnalyzers()[$fileExtension]) + || isset($this->additionalFileTypeAnalyzers[$fileExtension]) ) { throw new LogicException( sprintf('Cannot redeclare analyzer for file-type %s', $fileExtension), From 19b1a33a20609fbb8b8ababfe899de6af122fa3c Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Sat, 13 Jan 2024 11:18:48 +0100 Subject: [PATCH 47/63] fix possibly undefined array key in keyed array doesnt include null when not validated Fix https://psalm.dev/r/b153d0d248 to return 'a'|null instead of 'a' - this is required as otherwise empty would report RedundantCondition errors now which would bring back https://github.com/vimeo/psalm/issues/2681 --- .../Expression/Fetch/ArrayFetchAnalyzer.php | 8 ++++++-- tests/ArrayAccessTest.php | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php index 4a3a1f5c903..753e2891920 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php @@ -313,14 +313,18 @@ public static function analyze( && !$context->inside_unset && ($stmt_var_type && !$stmt_var_type->hasMixed()) ) { - IssueBuffer::maybeAdd( + if (IssueBuffer::accepts( new PossiblyUndefinedArrayOffset( 'Possibly undefined array key ' . $keyed_array_var_id . ' on ' . $stmt_var_type->getId(), new CodeLocation($statements_analyzer->getSource(), $stmt), ), $statements_analyzer->getSuppressedIssues(), - ); + )) { + $stmt_type = $stmt_type->getBuilder()->addType(new TNull())->freeze(); + } + } elseif ($stmt_type->possibly_undefined) { + $stmt_type = $stmt_type->getBuilder()->addType(new TNull())->freeze(); } $stmt_type = $stmt_type->setPossiblyUndefined(false); diff --git a/tests/ArrayAccessTest.php b/tests/ArrayAccessTest.php index 8bc2a488fc1..91ef428f99b 100644 --- a/tests/ArrayAccessTest.php +++ b/tests/ArrayAccessTest.php @@ -654,6 +654,19 @@ function f(array $p): void '$x3===' => "array{b: 'value'}", ], ], + 'possiblyUndefinedArrayOffsetKeyedArray' => [ + 'code' => ' [ + '$x===' => '"a"|null', + ], + 'ignored_issues' => ['PossiblyUndefinedArrayOffset'], + ], 'domNodeListAccessible' => [ 'code' => ' Date: Fri, 12 Jan 2024 23:37:45 +0100 Subject: [PATCH 48/63] fix bugs in tests --- tests/ArrayAccessTest.php | 19 +++++++++-- tests/FunctionCallTest.php | 4 +-- tests/ImmutableAnnotationTest.php | 2 +- tests/JsonOutputTest.php | 3 +- tests/Loop/DoTest.php | 2 +- tests/Loop/WhileTest.php | 4 +-- tests/MethodCallTest.php | 14 ++++---- tests/MethodSignatureTest.php | 6 ++-- tests/PropertyTypeTest.php | 8 +++-- tests/ReturnTypeTest.php | 6 ++++ tests/SwitchTypeTest.php | 2 +- tests/Template/ClassTemplateTest.php | 2 ++ .../AssignmentInConditionalTest.php | 6 ++-- tests/TypeReconciliation/ConditionalTest.php | 10 ++++++ tests/TypeReconciliation/EmptyTest.php | 8 ++++- tests/TypeReconciliation/IssetTest.php | 2 +- .../RedundantConditionTest.php | 15 ++++++--- tests/TypeReconciliation/TypeAlgebraTest.php | 32 +++++++++++++++++++ tests/UnusedVariableTest.php | 18 +++++------ 19 files changed, 121 insertions(+), 42 deletions(-) diff --git a/tests/ArrayAccessTest.php b/tests/ArrayAccessTest.php index 91ef428f99b..af33aa025f8 100644 --- a/tests/ArrayAccessTest.php +++ b/tests/ArrayAccessTest.php @@ -663,7 +663,7 @@ function f(array $p): void $x = $d[0];', 'assertions' => [ - '$x===' => '"a"|null', + '$x===' => '\'a\'', ], 'ignored_issues' => ['PossiblyUndefinedArrayOffset'], ], @@ -1349,7 +1349,7 @@ public function __toString() { echo $a[new Foo];', 'error_message' => 'InvalidArrayOffset', ], - 'possiblyUndefinedIntArrayOffet' => [ + 'possiblyUndefinedIntArrayOffset' => [ 'code' => ' 'PossiblyUndefinedArrayOffset', ], - 'possiblyUndefinedStringArrayOffet' => [ + 'possiblyUndefinedStringArrayOffset' => [ 'code' => ' 0.5, "b" => 1.5, "c" => new Exception()]);', 'error_message' => 'InvalidArgument', ], + 'possiblyUndefinedArrayOffsetKeyedArray' => [ + 'code' => ' 'PossiblyUndefinedArrayOffset', + ], ]; } } diff --git a/tests/FunctionCallTest.php b/tests/FunctionCallTest.php index e63636dff43..4d997070211 100644 --- a/tests/FunctionCallTest.php +++ b/tests/FunctionCallTest.php @@ -1937,7 +1937,7 @@ function badpattern() { 'strposAllowDictionary' => [ 'code' => ' [ @@ -2138,7 +2138,7 @@ function foo(A $a1, A $a2 = null): void 'strposFirstParamAllowClassString' => [ 'code' => ' [ diff --git a/tests/ImmutableAnnotationTest.php b/tests/ImmutableAnnotationTest.php index da36f660df9..07994b59b44 100644 --- a/tests/ImmutableAnnotationTest.php +++ b/tests/ImmutableAnnotationTest.php @@ -300,7 +300,7 @@ public function getError(): ?string { $dto = new DTO("BOOM!"); - if ($dto->getError()) { + if ($dto->getError() !== null) { takesString($dto->getError()); }', ], diff --git a/tests/JsonOutputTest.php b/tests/JsonOutputTest.php index c20d7b9d721..0fefa3f6dec 100644 --- a/tests/JsonOutputTest.php +++ b/tests/JsonOutputTest.php @@ -138,6 +138,7 @@ function fooFoo() { ], 'singleIssueForTypeDifference' => [ 'code' => ' 1, 'message' => 'Operand of type non-falsy-string is always truthy', - 'line' => 4, + 'line' => 5, 'error' => '$b', ], ]; diff --git a/tests/Loop/DoTest.php b/tests/Loop/DoTest.php index 5c125de7fac..0c703985b25 100644 --- a/tests/Loop/DoTest.php +++ b/tests/Loop/DoTest.php @@ -245,7 +245,7 @@ function bar(?string &$i) : void {} $c = null; do { - if (!$c) { + if ($c === null || $c === "" || $c === "0") { foo($c); } else { bar($c); diff --git a/tests/Loop/WhileTest.php b/tests/Loop/WhileTest.php index 73dd8085bdf..3056bdc8660 100644 --- a/tests/Loop/WhileTest.php +++ b/tests/Loop/WhileTest.php @@ -155,7 +155,7 @@ function foo(): ?A { } while ($a = foo()) { - if ($a->bar) {} + if ($a->bar !== null) {} }', ], 'whileTrueWithBreak' => [ @@ -271,7 +271,7 @@ function bar(?string &$i) : void {} $c = null; while (rand(0, 1)) { - if (!$c) { + if ($c === null || $c === "" || $c === "0") { foo($c); } else { bar($c); diff --git a/tests/MethodCallTest.php b/tests/MethodCallTest.php index 9b8ba5b72b2..4c411170272 100644 --- a/tests/MethodCallTest.php +++ b/tests/MethodCallTest.php @@ -149,7 +149,7 @@ function printInt(int $int): void { $obj = new SomeClass(); - if ($obj->getInt()) { + if ($obj->getInt() !== null) { printInt($obj->getInt()); }', ); @@ -185,7 +185,7 @@ function printInt(int $int): void { $obj = new SomeClass(); - if ($obj->getInt()) { + if ($obj->getInt() !== null) { printInt($obj->getInt()); }', ); @@ -936,7 +936,7 @@ final public function getA() { $a = new A(); - if ($a->getA()) { + if ($a->getA() !== null) { echo strlen($a->getA()); }', ], @@ -1007,7 +1007,7 @@ function printInt(int $int): void { $obj = new SomeClass(); - if ($obj->getInt()) { + if ($obj->getInt() !== null) { printInt($obj->getInt()); }', ], @@ -1031,7 +1031,7 @@ function printInt(int $int): void { $obj = new SomeClass(); - if ($obj->getInt()) { + if ($obj->getInt() !== null) { printInt($obj->getInt()); }', ], @@ -1631,7 +1631,7 @@ function getA() { } function foo(A $a) : void { - if ($a->getA()) { + if ($a->getA() !== null) { echo strlen($a->getA()); } } @@ -1697,7 +1697,7 @@ function printInt(int $int): void { $obj = new SomeClass(); - if ($obj->getInt()) { + if ($obj->getInt() !== null) { printInt($obj->getInt()); }', 'error_message' => 'PossiblyNullArgument', diff --git a/tests/MethodSignatureTest.php b/tests/MethodSignatureTest.php index a740cf0f4a9..e973c0f7e77 100644 --- a/tests/MethodSignatureTest.php +++ b/tests/MethodSignatureTest.php @@ -311,7 +311,7 @@ public function foo(string $s): ?string { class B extends A { public function foo(?string $s): string { - return $s ?: "hello"; + return $s !== null ? $s : "hello"; } } @@ -327,7 +327,7 @@ public function foo(string $s): string { class B extends A { public function foo(string $s = null): string { - return $s ?: "hello"; + return $s !== null ? $s : "hello"; } } @@ -1044,7 +1044,7 @@ public function fooFoo(int $a, bool $c): void { 'code' => 'getX()) { + if (is_int($x->getX())) { XCollector::modify(); if ($x->getX() === null) {} } @@ -221,7 +221,7 @@ public function getX() : ?int { } function testX(X $x): void { - if ($x->getX()) { + if ($x->getX() !== null) { XCollector::modify(); if ($x->getX() === null) {} } @@ -255,7 +255,7 @@ public function __construct(?int $x) { } function testX(X $x): void { - if ($x->x) { + if ($x->x !== null) { XCollector::modify(); if ($x->x === null) {} } @@ -686,6 +686,8 @@ class A { } echo substr($a->aa, 1);', + 'assertions' => [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'nullableStaticPropertyWithIfCheck' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'returnTypeNotEmptyCheckInElseIf' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'returnTypeNotEmptyCheckInElse' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'returnTypeAfterIf' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'noCrashTemplateInsideGenerator' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'assignmentInIf' => [ 'code' => ' 5) { - } elseif (($a = rand(0, 1) ? new A : null) && $a->foo) {}', + } elseif (($a = rand(0, 1) ? new A : null) && is_string($a->foo)) {}', ], 'noParadoxAfterConditionalAssignment' => [ 'code' => ' 'InvalidReturnStatement', - 'ignored_issues' => [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], 'php_version' => '8.0', ], 'assignmentInBranchOfAndReferencedAfterIf' => [ diff --git a/tests/TypeReconciliation/ConditionalTest.php b/tests/TypeReconciliation/ConditionalTest.php index 2209c2f163d..5a070688870 100644 --- a/tests/TypeReconciliation/ConditionalTest.php +++ b/tests/TypeReconciliation/ConditionalTest.php @@ -594,6 +594,8 @@ function Foo($value = null) : bool { } return false; }', + 'assertions' => [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'numericStringAssertion' => [ 'code' => ' 5) {} } }', + 'assertions' => [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'arrayUnionTypeSwitching' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'propertySetOnElementInConditional' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'issetAssertionOnStaticProperty' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'nonEmptyStringAfterLiteralCheck' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'emptyExceptionReconciliationAfterIf' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'alwaysBoolResult' => [ 'code' => ' [], - 'ignored_issues' => ['MixedAssignment', 'MissingParamType', 'MixedArgument'], + 'ignored_issues' => ['MixedAssignment', 'MissingParamType', 'MixedArgument', 'RiskyTruthyFalsyComparison'], ], 'multipleEmptiesInCondition' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'reconcileEmptyTwiceWithoutReturn' => [ 'code' => ' [], - 'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess'], + 'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess', 'RiskyTruthyFalsyComparison'], ], 'mixedArrayIssetGetStringVar' => [ 'code' => ' [], + 'ignored_issues' => [ + 'RiskyTruthyFalsyComparison', + ], ], 'noRedundantConditionAfterAssignment' => [ 'code' => 'foo) {} + if ($i->foo !== null) {} break; default: @@ -180,7 +184,7 @@ function makeA() { } if ($a) {}', 'assertions' => [], - 'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess'], + 'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess', 'RiskyTruthyFalsyComparison'], ], 'noComplaintWithIsNumericThenIsEmpty' => [ 'code' => ' [], 'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess'], ], @@ -539,7 +543,7 @@ function bar(string $b) : bool { exit; } - if ($i) {}', + if ($i !== array() && $i !== "" && $i !== "0") {}', ], 'emptyWithoutKnowingArrayType' => [ 'code' => ' ' 'RedundantCondition', + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'refineTypeInMethodCall' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'twoVarLogicNotNestedWithAllPathsReturning' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'twoVarLogicNotNestedWithAssignmentBeforeReturn' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'invertedTwoVarLogicNotNested' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'invertedTwoVarLogicNotNestedWithAssignmentBeforeReturn' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'twoVarLogicNotNestedWithElseifAndNoNegations' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'threeVarLogicNotNestedWithNoRedefinitionsWithClasses' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'threeVarLogicNotNestedAndOrWithNoRedefinitions' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'twoVarLogicNotNestedWithElseifCorrectlyNegatedInElseIf' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'lotsaTruthyStatements' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'cancelOutDifferentStatement' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'moreChecks' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'compareToIntInsideIfCNF' => [ 'code' => ' [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'ternaryAssertionOnBool' => [ 'code' => ' 'NullableReturnStatement', + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'invertedTwoVarLogicNotNestedWithElseif' => [ 'code' => ' 'NullableReturnStatement', + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'threeVarLogicWithElseifAndAnd' => [ 'code' => ' 'TypeDoesNotContainType', + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'twoVarLogicNotNestedWithElseifIncorrectlyReinforcedInIf' => [ 'code' => ' 'RedundantCondition', + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'repeatedIfStatements' => [ 'code' => ' 'TypeDoesNotContainType', + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'repeatedConditionals' => [ 'code' => ' 'RedundantCondition', + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], ], 'dependentTypeInvalidated' => [ 'code' => ' [ @@ -128,10 +128,10 @@ function foo(string $a): void { 'dummyByRefVar' => [ 'code' => 'getMessage(); } - if ($s) {} + if ($s !== null) {} }', ], 'throwWithMessageCallAndAssignmentInCatchAndReference' => [ @@ -940,7 +940,7 @@ function foo() : void { if ($foo) {} } catch (Exception $e) {} - if ($foo) {}', + if ($foo !== false && $foo !== 0) {}', ], 'useTryAssignedVariableInsideFinally' => [ 'code' => ' [], - 'ignored_issues' => [], + 'ignored_issues' => ['RiskyTruthyFalsyComparison'], 'php_version' => '8.0', ], 'concatWithUnknownProperty' => [ @@ -3165,7 +3165,7 @@ function bar() : void { $user = $user_id; } - if ($user) { + if ($user !== null && $user !== 0) { $a = 0; for ($i = 1; $i <= 10; $i++) { $a += $i; @@ -3185,7 +3185,7 @@ function bar() : void { $user = $user_id; } - if ($user) { + if ($user !== null && $user !== 0) { $a = 0; foreach ([1, 2, 3] as $i) { $a += $i; From dca17bcb6affce958f4650172db70379138a6d46 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Sat, 13 Jan 2024 13:05:43 +0100 Subject: [PATCH 49/63] unrelated fix spelling --- tests/ArrayAccessTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ArrayAccessTest.php b/tests/ArrayAccessTest.php index af33aa025f8..88eb7d15e52 100644 --- a/tests/ArrayAccessTest.php +++ b/tests/ArrayAccessTest.php @@ -691,7 +691,7 @@ function example(array $x, $y) : void { 'assertions' => [], 'ignored_issues' => ['MixedArgument', 'MixedArrayOffset', 'MissingParamType'], ], - 'suppressPossiblyUndefinedStringArrayOffet' => [ + 'suppressPossiblyUndefinedStringArrayOffset' => [ 'code' => ' Date: Sat, 13 Jan 2024 13:03:28 +0100 Subject: [PATCH 50/63] simplify and remove redundant variable --- .../Block/IfConditionalAnalyzer.php | 34 ++++++++----------- .../Expression/BooleanNotAnalyzer.php | 34 ++++++++----------- .../Statements/Expression/EmptyAnalyzer.php | 34 ++++++++----------- 3 files changed, 45 insertions(+), 57 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php index 23b88d0710e..ebbc0a66e4a 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php @@ -371,34 +371,30 @@ public static function handleParadoxicalCondition( } elseif (!($stmt instanceof PhpParser\Node\Expr\BinaryOp\NotIdentical) && !($stmt instanceof PhpParser\Node\Expr\BinaryOp\Identical) && !($stmt instanceof PhpParser\Node\Expr\BooleanNot)) { - $has_both = false; - $both_types = $type->getBuilder(); if (count($type->getAtomicTypes()) > 1) { + $both_types = $type->getBuilder(); foreach ($both_types->getAtomicTypes() as $key => $atomic_type) { if ($atomic_type->isTruthy() || $atomic_type->isFalsy() || $atomic_type instanceof TBool) { $both_types->removeType($key); - continue; } - - $has_both = true; } - } - if ($has_both) { - $both_types = $both_types->freeze(); - IssueBuffer::maybeAdd( - new RiskyTruthyFalsyComparison( - 'Operand of type ' . $type->getId() . ' contains ' . - 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . - $both_types->getId() . ', which can be falsy and truthy. ' . - 'This can cause possibly unexpected behavior. Use strict comparison instead.', - new CodeLocation($statements_analyzer, $stmt), - $type->getId(), - ), - $statements_analyzer->getSuppressedIssues(), - ); + if (count($both_types->getAtomicTypes()) > 0) { + $both_types = $both_types->freeze(); + IssueBuffer::maybeAdd( + new RiskyTruthyFalsyComparison( + 'Operand of type ' . $type->getId() . ' contains ' . + 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . + $both_types->getId() . ', which can be falsy and truthy. ' . + 'This can cause possibly unexpected behavior. Use strict comparison instead.', + new CodeLocation($statements_analyzer, $stmt), + $type->getId(), + ), + $statements_analyzer->getSuppressedIssues(), + ); + } } } } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php index 71f6e19324f..93d17c3f7f5 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php @@ -45,34 +45,30 @@ public static function analyze( } elseif ($expr_type->isAlwaysFalsy()) { $stmt_type = new TTrue($expr_type->from_docblock); } else { - $has_both = false; - $both_types = $expr_type->getBuilder(); if (count($expr_type->getAtomicTypes()) > 1) { + $both_types = $expr_type->getBuilder(); foreach ($both_types->getAtomicTypes() as $key => $atomic_type) { if ($atomic_type->isTruthy() || $atomic_type->isFalsy() || $atomic_type instanceof TBool) { $both_types->removeType($key); - continue; } - - $has_both = true; } - } - if ($has_both) { - $both_types = $both_types->freeze(); - IssueBuffer::maybeAdd( - new RiskyTruthyFalsyComparison( - 'Operand of type ' . $expr_type->getId() . ' contains ' . - 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . - $both_types->getId() . ', which can be falsy and truthy. ' . - 'This can cause possibly unexpected behavior. Use strict comparison instead.', - new CodeLocation($statements_analyzer, $stmt), - $expr_type->getId(), - ), - $statements_analyzer->getSuppressedIssues(), - ); + if (count($both_types->getAtomicTypes()) > 0) { + $both_types = $both_types->freeze(); + IssueBuffer::maybeAdd( + new RiskyTruthyFalsyComparison( + 'Operand of type ' . $expr_type->getId() . ' contains ' . + 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . + $both_types->getId() . ', which can be falsy and truthy. ' . + 'This can cause possibly unexpected behavior. Use strict comparison instead.', + new CodeLocation($statements_analyzer, $stmt), + $expr_type->getId(), + ), + $statements_analyzer->getSuppressedIssues(), + ); + } } $stmt_type = new TBool(); diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php index 02fae12fd44..8dbcca2f9bb 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php @@ -64,34 +64,30 @@ public static function analyze( } elseif ($expr_type->isAlwaysFalsy()) { $stmt_type = new TTrue($expr_type->from_docblock); } else { - $has_both = false; - $both_types = $expr_type->getBuilder(); if (count($expr_type->getAtomicTypes()) > 1) { + $both_types = $expr_type->getBuilder(); foreach ($both_types->getAtomicTypes() as $key => $atomic_type) { if ($atomic_type->isTruthy() || $atomic_type->isFalsy() || $atomic_type instanceof TBool) { $both_types->removeType($key); - continue; } - - $has_both = true; } - } - if ($has_both) { - $both_types = $both_types->freeze(); - IssueBuffer::maybeAdd( - new RiskyTruthyFalsyComparison( - 'Operand of type ' . $expr_type->getId() . ' contains ' . - 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . - $both_types->getId() . ', which can be falsy and truthy. ' . - 'This can cause possibly unexpected behavior. Use strict comparison instead.', - new CodeLocation($statements_analyzer, $stmt), - $expr_type->getId(), - ), - $statements_analyzer->getSuppressedIssues(), - ); + if (count($both_types->getAtomicTypes()) > 0) { + $both_types = $both_types->freeze(); + IssueBuffer::maybeAdd( + new RiskyTruthyFalsyComparison( + 'Operand of type ' . $expr_type->getId() . ' contains ' . + 'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' . + $both_types->getId() . ', which can be falsy and truthy. ' . + 'This can cause possibly unexpected behavior. Use strict comparison instead.', + new CodeLocation($statements_analyzer, $stmt), + $expr_type->getId(), + ), + $statements_analyzer->getSuppressedIssues(), + ); + } } $stmt_type = new TBool(); From 5643cf53d4983b75a7772cd96b53b109c3a020a9 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Sat, 13 Jan 2024 16:00:57 +0100 Subject: [PATCH 51/63] fix mixed test not actually checking mixed (since superglobals have a more specific type now) --- tests/TypeReconciliation/ConditionalTest.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/TypeReconciliation/ConditionalTest.php b/tests/TypeReconciliation/ConditionalTest.php index 5a070688870..4d48add4f1d 100644 --- a/tests/TypeReconciliation/ConditionalTest.php +++ b/tests/TypeReconciliation/ConditionalTest.php @@ -1168,11 +1168,19 @@ function Foo($width, $height) : void { ], 'notEmptyCheckOnMixedInTernary' => [ 'code' => ' [ 'code' => ' Date: Mon, 15 Jan 2024 10:09:49 +0100 Subject: [PATCH 52/63] change error level to 2 --- docs/running_psalm/error_levels.md | 2 +- src/Psalm/Issue/RiskyTruthyFalsyComparison.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/running_psalm/error_levels.md b/docs/running_psalm/error_levels.md index df53f5227f6..f3df22adb45 100644 --- a/docs/running_psalm/error_levels.md +++ b/docs/running_psalm/error_levels.md @@ -173,7 +173,6 @@ Level 5 and above allows a more non-verifiable code, and higher levels are even - [TooManyArguments](issues/TooManyArguments.md) - [TypeDoesNotContainNull](issues/TypeDoesNotContainNull.md) - [TypeDoesNotContainType](issues/TypeDoesNotContainType.md) -- [RiskyTruthyFalsyComparison](issues/RiskyTruthyFalsyComparison.md) - [UndefinedMagicMethod](issues/UndefinedMagicMethod.md) - [UndefinedMagicPropertyAssignment](issues/UndefinedMagicPropertyAssignment.md) - [UndefinedMagicPropertyFetch](issues/UndefinedMagicPropertyFetch.md) @@ -245,6 +244,7 @@ Level 5 and above allows a more non-verifiable code, and higher levels are even - [RedundantConditionGivenDocblockType](issues/RedundantConditionGivenDocblockType.md) - [RedundantFunctionCallGivenDocblockType](issues/RedundantFunctionCallGivenDocblockType.md) - [ReferenceConstraintViolation](issues/ReferenceConstraintViolation.md) +- [RiskyTruthyFalsyComparison](issues/RiskyTruthyFalsyComparison.md) - [UndefinedTrace](issues/UndefinedTrace.md) - [UnresolvableInclude](issues/UnresolvableInclude.md) - [UnsafeInstantiation](issues/UnsafeInstantiation.md) diff --git a/src/Psalm/Issue/RiskyTruthyFalsyComparison.php b/src/Psalm/Issue/RiskyTruthyFalsyComparison.php index 9150aa30b8c..68ab4e1322b 100644 --- a/src/Psalm/Issue/RiskyTruthyFalsyComparison.php +++ b/src/Psalm/Issue/RiskyTruthyFalsyComparison.php @@ -6,7 +6,7 @@ final class RiskyTruthyFalsyComparison extends CodeIssue { - public const ERROR_LEVEL = 4; + public const ERROR_LEVEL = 2; public const SHORTCODE = 356; public function __construct(string $message, CodeLocation $code_location, ?string $dupe_key) From 4b418918299e9846ca95c2f9451a2a8fa8063135 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:33:46 +0100 Subject: [PATCH 53/63] update baseline --- psalm-baseline.xml | 1874 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1868 insertions(+), 6 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 71cc2ef6324..85f358308e2 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,186 @@ - + + + + mapper]]> + + + + + $items + + + + + $returnType + attrGroups]]> + byRef]]> + expr]]> + params]]> + returnType]]> + static]]> + + + + + + + + $returnType + attrGroups]]> + byRef]]> + params]]> + returnType]]> + static]]> + stmts]]> + uses]]> + + + + + $items + + + + + $parts + + + + + $conds + + + + + $parts + $parts + $parts + + + + + $stmts + + + + + $stmts + + + + + $returnType + attrGroups]]> + byRef]]> + flags]]> + params]]> + returnType]]> + stmts]]> + + + + + attrGroups]]> + extends]]> + flags]]> + implements]]> + stmts]]> + + + + + $stmts + + + + + $stmts + + + + + $stmts + + + + + $stmts + + + + + cond]]> + init]]> + loop]]> + stmts]]> + + + + + byRef]]> + keyVar]]> + stmts]]> + + + + + $returnType + attrGroups]]> + byRef]]> + params]]> + returnType]]> + stmts]]> + + + + + else]]> + elseifs]]> + stmts]]> + + + + + attrGroups]]> + extends]]> + stmts]]> + + + + + $stmts + + + + + attrGroups]]> + stmts]]> + + + + + $stmts + + + + + $stmts + + + + + static::getDefaultDescription() + static::getDefaultDescription() + static::getDefaultDescription() + static::getDefaultName() + static::getDefaultName() + static::getDefaultName() + + + $name + + tags['variablesfrom'][0]]]> @@ -12,6 +193,25 @@ $matches[1] + + + cased_name]]> + + + + + !$appearing_method_id + + + + + docblock_line_number]]> + docblock_line_number]]> + docblock_start]]> + docblock_start_line_number]]> + text]]> + + $const_name @@ -19,11 +219,83 @@ $symbol_name $symbol_parts[1] + + !$function_name + namespace]]> + namespace]]> + namespace]]> + namespace_first_stmt_start]]> + uses_end]]> + $file_path + insertText]]> + symbol, '()')]]> + symbol, '()')]]> + symbol, '()')]]> + symbol, '()')]]> + symbol, '::')]]> + symbol, '::')]]> + symbol, '\\')]]> + + + + + + + + + + + + + !$composer_json + !$config_path + !$file_path + + $cwd + $dir + function_id]]> + + $issue_handler_children + $parent_issue_type + composer_class_loader->findFile($pluginClassName)]]> + autoloader]]> + localName, $offset)]]> + name, $offset - strlen($file_contents))]]> + + + + + $suggested_dir + file_path, 'stub')]]> + file_path, 'vendor')]]> + + + !$directory_path + !$file_path + !$glob_directory_path + !$glob_file_path + directory]]> + file]]> + referencedClass]]> + referencedConstant]]> + referencedFunction]]> + referencedMethod]]> + referencedProperty]]> + referencedVariable]]> + glob($parts[0], GLOB_NOSORT) + glob($parts[0], GLOB_ONLYDIR | GLOB_NOSORT) + + + + + + + @@ -32,6 +304,17 @@ $matches[3] + + + $creating_conditional_id + $creating_conditional_id + + + + + name->name ?? null !== "name"]]> + + $comments[0] @@ -39,11 +322,147 @@ props[0]]]> $uninitialized_variables[0] + + !$declaring_property_class + !$fq_class_name + self]]> + self]]> + self]]> + self]]> + template_extended_params]]> + template_types]]> + $class_template_params + initialized_class]]> + $parent_fq_class_name + getStmts()]]> + getStmts()]]> + template_extended_params]]> + template_types]]> + classlike_storage_provider->get($original_fq_classlike_name), + strtolower($stmt->name->name), + $this_object_type, + )]]> + $property_name + + !$appearing_property_class + self]]> + !$declaring_property_class + self]]> + template_types]]> + $resolved_name + template_covariants]]> + template_extended_params]]> + template_types]]> + template_types]]> + + + + + self]]> + self]]> + self]]> + + + + + !$original_type + description]]> + var_id]]> + !$var_type_tokens + $brackets + $template_type_map + $type_aliases + line_number]]> + type_end]]> + type_start]]> + + + + + $namespace_name + $namespace_name + root_file_name]]> + root_file_path]]> + + + + + $namespace + $namespace + getNamespace()]]> + + + + + getStmts()]]> + $class_template_params + self]]> + self]]> + $fq_class_name + $self_fq_class_name + + + + + calling_method_id]]> + cased_name]]> + cased_name]]> + + template_types]]> + template_types]]> + $cased_method_id + $cased_method_id + $cased_method_id + $cased_method_id + $cased_method_id + self]]> + self]]> + self]]> + self]]> + self]]> + $context_self + $hash + $namespace + $parent_fqcln + $parent_fqcln + cased_name]]> + template_types]]> + $template_types + function->getStmts()]]> + source->getTemplateTypeMap()]]> + storage->template_types]]> + + + + + + !$calling_method_id + self]]> + $appearing_method_class + $appearing_method_class + self]]> + $context_self + + + + + template_types]]> + cased_name]]> + cased_name]]> + cased_name]]> + template_extended_params]]> + template_extended_params]]> + template_extended_params]]> + defining_fqcln]]> + @@ -53,22 +472,86 @@ $php_minor_version $source_parts[1] + + self]]> + + $potential_file_path + + + + + + branch_point]]> + cond]]> + + branch_point]]> + if (AtomicTypeComparator::isContainedBy( if (AtomicTypeComparator::isContainedBy( + + var_id]]> + var_id]]> + $calling_type_params + branch_point]]> + template_types]]> + getTemplateTypeMap()]]> + line_number]]> + type_end]]> + type_start]]> + $var_id + $var_id + + + + + negatable_if_types]]> + getTemplateTypeMap()]]> + + + + + getTemplateTypeMap()]]> + getTemplateTypeMap()]]> + + + + + getTemplateTypeMap()]]> + + + + + branch_point]]> + branch_point]]> + branch_point]]> + assigned_var_ids]]> + new_vars]]> + redefined_vars]]> + getTemplateTypeMap()]]> + assigned_var_ids += $switch_scope->new_assigned_var_ids]]> + + !$switch_var_id + new_assigned_var_ids]]> + new_vars_in_scope]]> + possibly_redefined_vars]]> + possibly_redefined_vars]]> + redefined_vars]]> + $switch_var_id + @@ -76,6 +559,29 @@ leftover_statements[0]]]> traverse([$switch_condition])[0]]]> + + branch_point]]> + $nested_or_options + $switch_var_id + $switch_var_id + $switch_var_id + $type_statements + + + + + branch_point]]> + + + + + branch_point]]> + + + + + $var_id + @@ -108,23 +614,204 @@ getArgs()[0]]]> getArgs()[0]]]> + + !$var_name + !$var_type + ')]]> + + $array_root + $count_equality_position + $count_equality_position + $count_equality_position + $count_inequality_position + $count_inequality_position + $count_inequality_position + $false_position + $false_position + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name + $first_var_name_in_array_argument + $get_debug_type_position + $get_debug_type_position + $getclass_position + $getclass_position + $gettype_position + $gettype_position + $if_false_assertions + $if_true_assertions + $inferior_value_position + $other_var_name + $superior_value_position + $this_class_name + $this_class_name + $this_class_name + $true_position + $true_position + $typed_value_position + $typed_value_position + $var_id + $var_id + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name + $var_name_left + $var_name_right + $var_type + $var_type + $var_type + self::hasReconcilableNonEmptyCountEqualityCheck($conditional) + + + + + !$parent_var_id + $object_id + $parent_var_id + $parent_var_id + $root_var_id + $root_var_id + $root_var_id + $root_var_id + $root_var_id + $var_id + $var_var_id + + + + + self]]> + !$var_id + $appearing_property_class + $class_template_params + $class_template_params + calling_method_id]]> + calling_method_id]]> + self]]> + self]]> + self]]> + $declaring_property_class + getter_method]]> + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + $var_property_id + $var_property_id + calling_method_id, '::__clone')]]> + calling_method_id, '::__construct')]]> + calling_method_id, '::__unserialize')]]> + calling_method_id, '::unserialize')]]> + $new_property_name + + calling_method_id]]> + $var_id + $var_id + + + var_id]]> + ')]]> + ')]]> + + $assign_value_id + calling_method_id]]> + $extended_var_id + $extended_var_id + $extended_var_id + $extended_var_id + $extended_var_id + $list_var_id + $list_var_id + $list_var_id + $prop_name + $root_var_id + line_number]]> + type_end]]> + type_start]]> + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + vars_in_scope[$lhs_var_id] = &$context->vars_in_scope[$rhs_var_id]]]> + + + getTemplateTypeMap()]]> + + $invalid_left_messages[0] $invalid_right_messages[0] + + + branch_point]]> + $var_id + + verifyType @@ -134,6 +821,54 @@ $parts[1] + + !$container_class + $cased_method_id + $cased_method_id + $cased_method_id + $cased_method_id + $cased_method_id + $class_generic_params + calling_function_id]]> + calling_function_id]]> + calling_method_id]]> + $self_fq_class_name + $static_fq_class_name + $var_id + value, '::')]]> + value, '::')]]> + + + + + self]]> + $cased_method_id + $cased_method_id + $cased_method_id + $cased_method_id + $cased_method_id + $cased_method_id + calling_method_id]]> + calling_method_id]]> + calling_method_id]]> + calling_method_id]]> + calling_method_id]]> + calling_method_id]]> + calling_method_id]]> + sinks]]> + $function_params + $function_params + $function_params + template_types]]> + $method_id + $method_id + $method_id + $method_id + $var_id + $var_id + $var_id + getFQCLN())]]> + @@ -142,19 +877,117 @@ $args[1] $method_name + + !$container_class + calling_method_id]]> + $var_id + + + + + !$template_types + !$template_types + template_types]]> + $method_name + $overridden_template_types + template_extended_params]]> + template_types]]> + + + $function_name + $function_name + + + getArgs()[0]->value]]> + getArgs()[0]]]> $parts[1] + + function_id]]> + function_id]]> + function_id]]> + function_id]]> + function_id]]> + function_id]]> + getTemplateTypeMap()]]> + value, '::')]]> + $method + + self]]> + self]]> + self]]> + template_types]]> + template_types]]> + + + + + mixin_declaring_fqcln]]> + mixin_declaring_fqcln]]> + template_types]]> + template_types]]> + calling_method_id]]> + calling_method_id]]> + self]]> + $lhs_var_id + $mixin_class_template_params + + + + + $class_template_params + calling_method_id]]> + calling_method_id]]> + $lhs_var_id + template_types]]> + template_types]]> + + + + + $caller_identifier + + + + + this_property_mutations]]> + + + + + specialization_key]]> + $var_id + + + + + self]]> + self]]> + $appearing_method_name + + + + + $found_generic_params + $found_generic_params + $found_generic_params + $found_generic_params + $found_generic_params + $found_generic_params + $intersection_method_id + $intersection_method_id + @@ -165,23 +998,115 @@ non_existent_interface_method_ids[0]]]> non_existent_magic_method_ids[0]]]> + + getFQCLN()]]> + $lhs_var_id + $lhs_var_id + $lhs_var_id + + + + + getFQCLN()]]> + $path_to_file + $var_id + ')]]> + + + + + + calling_method_id]]> + self]]> + $fq_class_name + $fq_class_name + getFullyQualifiedFunctionMethodOrNamespaceName()]]> + template_extended_params]]> + template_types]]> + template_types]]> + template_types]]> + + + + + parent_class]]> + $child_fq_class_name + calling_method_id]]> + self]]> + self]]> + + + + + self]]> + !$fq_class_name + mixin_declaring_fqcln]]> + parent_class]]> + parent_class]]> + calling_method_id]]> + calling_method_id]]> + self]]> + $new_method_name + + self]]> + self]]> + self]]> + self]]> + $found_generic_params + $found_generic_params + template_extended_params]]> + items[0]]]> items[1]]]> + + !$arg_var_id + $arg_var_id + $assertion_var_id + template_extended_params]]> + self]]> + self]]> + self]]> + template_types]]> + template_types]]> + $new_const_name $new_const_name + + self]]> + calling_method_id]]> + calling_method_id]]> + self]]> + self]]> + self]]> + self]]> + + + + + !$lhs_var_name + !$object_id + !$object_id + !$this_class_name + $object_id + $property_root + $resolved_name + $resolved_name + $root_var_id + $this_class_name + @@ -189,31 +1114,143 @@ $stmt_type $stmt_type + + $dim_var_id + $dim_var_id + $extended_var_id + $extended_var_id + $keyed_array_var_id + $keyed_array_var_id + $keyed_array_var_id + $keyed_array_var_id + $stmt_type + + self]]> + self]]> + $declaring_property_class + $declaring_property_class + template_types]]> + template_types]]> + $var_id + $var_id + $var_property_id + $var_property_id + $invalid_fetch_types[0] + + !$prop_name + calling_method_id]]> + calling_method_id]]> + $declaring_property_class + $stmt_var_id + $var_id + $var_id + $new_property_name + + !$prop_name + calling_method_id]]> + calling_method_id]]> + calling_method_id]]> + self]]> + $string_type + $var_id + $var_id + + + + + $branch_point + $branch_point + + + + + $var_id + + + + + !$evaled_path + !$var_id + $include_path + $left_string + $path_to_file + $right_string + $var_id + + + + + self]]> + + + + + !$switch_var_id + $switch_var_id + + + + + $fq_classlike_name + + + + + branch_point]]> + getTemplateTypeMap()]]> + getTemplateTypeMap()]]> + type_params[2]]]> + + var_id]]> + $class_template_params + declaring_yield_fqcn]]> + self]]> + line_number]]> + type_end]]> + type_start]]> + $method_name + + calling_function_id]]> + calling_method_id]]> + var_id]]> + calling_function_id]]> + self]]> + $found_generic_params + line_number]]> + type_end]]> + type_start]]> + + + + + $root_var_id + $var_id + @@ -231,21 +1268,84 @@ expr->getArgs()[0]]]> + + $branch_point + $new_issues + getNamespace()]]> + $possible_traced_variable_names + fake_this_class]]> + vars_to_initialize]]> + + + + + UndefinedFunction + UndefinedFunction + + + + + !$root_path + + + + error_baseline]]> + !$paths_to_check + !$root_path + + + $baseline_file_path + $cache_directory + threads]]> + $find_references_to + empty($baselineFile) + + + + + + !$root_path + $paths_to_check + $identifier_name + + !$last_arg + !$last_arg + !$last_arg + !$root_path + + + + + + !$config_file + !$end_psalm_open_tag + !$path_to_check + error_baseline]]> + $f_paths + $path_to_config + $stdin = fgets(STDIN) + getPHPVersionFromComposerJson()]]> + getPhpVersionFromConfig()]]> + + $trait + + + @@ -255,11 +1355,92 @@ $source_const_name $stub + + !$calling_fq_class_name + !$insert_pos + !$insert_pos + !$insert_pos + $calling_fq_class_name + $calling_fq_class_name + $calling_fq_class_name + $calling_fq_class_name + $calling_fq_class_name + $calling_fq_class_name + $calling_fq_class_name + $calling_fq_class_name + $calling_fq_class_name + $calling_fq_class_name + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $file_path + $file_path + $file_path + $file_path + $file_path + $migrated_source_fqcln + $migrated_source_fqcln + + + + + value]]> + $stub + + !$checked_file_path + !$root_file_path + $args + cased_name]]> + $namespace + + + + + !$return_type_string + + + + + !$calling_class_name + !$extends + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $found_generic_params + $old_method_id + $source_file_path + $source_file_path + $source_file_path + $source_file_path + $source_file_path + $source_file_path + $source_file_path + $source_file_path + + + + + + $mapped_name + template_extended_params]]> + template_extended_params]]> + template_extended_params]]> + template_types]]> + template_extended_params]]> + @@ -270,6 +1451,38 @@ $property_name $property_name + + calling_method_id]]> + calling_method_id]]> + calling_method_id]]> + + + + + $composer_file_path + cased_name]]> + cased_name]]> + + + + + specialization_key]]> + unspecialized_id]]> + escaped_taints]]> + unescaped_taints]]> + specialization_key]]> + path_types)]]> + + + + + + + + + + $specialization_key + @@ -280,28 +1493,110 @@ stmts[0]]]> $b_stmt_comments[0] + + stmts]]> + stmts]]> + $b[$y] + + + readEnv['CI_PR_NUMBER']]]> + + $exploded[1] $url + + + $var_end + $var_start + + + + + + new_php_return_type]]> + $last_arg_position + new_php_return_type]]> + new_phpdoc_return_type]]> + return_typehint_colon_start]]> + return_typehint_end]]> + return_typehint_end]]> + return_typehint_start]]> + return_typehint_start]]> + $php_type + new_phpdoc_return_type]]> + new_psalm_return_type]]> + return_type_description]]> + return_type_description]]> + + props[0]]]> + + new_php_type]]> + new_php_type]]> + new_phpdoc_type]]> + typehint_end]]> + typehint_end]]> + typehint_start]]> + typehint_start]]> + $preceding_semicolon_pos + new_phpdoc_type]]> + new_psalm_type]]> + type_description]]> + + + + + !$sockets + + + + + tmpIni]]> + + + + + empty($message) + + + + + TCPServerAddress]]> + TCPServerAddress]]> + onchangeLineLimit]]> + empty($additional_info) + $method_id_parts[1] + + + $arg_var_id + $arg_var_id + $left_var_id + $left_var_id + $right_var_id + $right_var_id + $var_id + $var_id + + $cs[0] @@ -313,6 +1608,17 @@ $replacement_stmts[0] $replacement_stmts[0] + + !$method_contents + parser->parse( + $hacky_class_fix, + $error_handler, + )]]> + parser->parse( + $fake_class, + $error_handler, + )]]> + @@ -321,18 +1627,56 @@ children[0]]]> children[1]]]> + + !$method_entry + + $l[4] $r[4] + + !$var_line_parts + newModifier]]> + $class_name + description]]> + inheritors]]> + yield]]> + template_types]]> + template_types]]> + template_types]]> + template_types]]> + template_types]]> + template_types]]> + template_types]]> + aliases->namespace]]> + aliases->namespace]]> + line_number]]> + type_end]]> + type_start]]> + + + + + $fq_classlike_name + $string_value + $string_value + $string_value + getArgs()[0]]]> getArgs()[1]]]> + + !$skip_if_descendants + !$skip_if_descendants + $include_path + $path_to_file + @@ -346,16 +1690,75 @@ $source_param_string + + namespace]]> + template_types]]> + template_types]]> + description]]> + return_type_end]]> + return_type_line_number]]> + return_type_line_number]]> + return_type_start]]> + template_types]]> + template_types]]> + template_types]]> + template_types]]> + $template_types + $template_types + $template_types + stmts[0]]]> + + stmts]]> + aliases->namespace]]> + aliases->namespace]]> + template_types]]> + $fq_classlike_name + $function_id + $function_id + $method_name_lc + stmts]]> + stmts]]> + stmts]]> + stmts]]> + aliases->namespace]]> + aliases->namespace]]> + + + + + $type_string + + + + + aliases->uses_start]]> + aliases->uses_start]]> + skip_if_descendants]]> + skip_if_descendants]]> + skip_if_descendants]]> + skip_if_descendants]]> + skip_if_descendants]]> + skip_if_descendants]]> + skip_if_descendants]]> + code_location->file_path, 'CoreGenericClasses.phpstub')]]> + code_location->file_path, 'CoreGenericFunctions.phpstub')]]> + file_path, 'CoreGenericIterators.phpstub')]]> + $cs[0] + + $offset_map + end_change]]> + start_change]]> + @@ -383,6 +1786,87 @@ getOption('config')]]> + + + !$path + $explicit_path + psalm_header]]> + psalm_tag_end_pos]]> + + + + + enabled_plugins]]> + + + + + !$root_cache_directory + $file_contents + $file_path + + + + + !$cache_directory + !$cache_directory + !$cache_directory + $cache_directory + + + + + cache->getFileMapCache()]]> + + + + + !$root_cache_directory + + + + + $result + + + + + $called_method_name + + + + + $extended_var_id + + + + + !$cache_directory + !$root_cache_directory + !$root_cache_directory + !$root_cache_directory + + + + + !$cache_directory + !$cache_directory + composer_lock_hash]]> + $cache_directory + + + + + !$key_column_name + + + + + $callable_extended_var_id + getTemplateTypeMap()]]> + getTemplateTypeMap()]]> + + $callable_method_name @@ -398,6 +1882,73 @@ $method_name + + + $fetch_class_name + + + + + !$call_args + + + + + $existing_file_contents + $existing_file_contents + $existing_file_contents + $existing_statements + $existing_statements + $existing_statements + $existing_statements + $file_changes + $file_path + parse($file_contents, $error_handler)]]> + parse($file_contents, $error_handler)]]> + + + + + + $first_line_padding + + + + + !$resolved_name + $mapped_type = $map[$offset_arg_value] ?? null + $mapped_type = $map[$offset_arg_value] ?? null + + + + + + + cased_name]]> + template_types]]> + parent_class]]> + template_types]]> + + + + + cased_name]]> + cased_name]]> + template_types]]> + + + + + $key + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + $var_id + + isContainedBy @@ -414,6 +1965,36 @@ TCallable|TClosure|null + + !$class_name + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + $calling_method_id + params]]> + $file_name + $file_name + $input_variadic_param_idx + $member_id + + + + + !($container_type_params_covariant[$i] ?? false) + + + + + $intersection_container_type_lower + + + + + $key + $key + $key + @@ -422,11 +2003,83 @@ $properties[0] $properties[0] + + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $var_id + $var_id + $var_id + $var_id + + + + + + !$count + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $key + $var_id + $var_id + $var_id + $var_id + + + + + template_extended_params]]> + getClassTemplateTypes + + + + $input_template_types + template_extended_params[$container_class])]]> + template_extended_params[$base_type->as_type->value])]]> + template_extended_params[$base_type->value])]]> + + @@ -437,11 +2090,48 @@ array_type_params[1]]]> array_type_params[1]]]> + + class_string_types]]> + floats]]> + ints]]> + named_object_types]]> + strings]]> + array_counts]]> + array_min_counts]]> + array_min_counts]]> + class_string_types]]> + class_string_types]]> + floats]]> + ints]]> + ints]]> + ints]]> + named_object_types]]> + strings]]> + strings]]> + strings]]> + strings]]> + value_types['string'] instanceof TNonFalsyString + ? $type->value + : $type->value !== '']]> + $shared_classlikes + $fallback_params + + template_types]]> + $params + $parent_class + $self_class + $self_class + $self_class + $self_class + $self_class + $self_class + $static_class_type + @@ -455,6 +2145,11 @@ array_keys($template_type_map[$fq_classlike_name])[0] array_keys($template_type_map[$template_param_name])[0] + + $extra_params + value, '::')]]> + value, '::')]]> + @@ -463,6 +2158,59 @@ $type_tokens[$i - 1] $type_tokens[$i - 1] + + $parent_fqcln + $self_fqcln + + + + + + !$fq_classlike_name + template_types]]> + template_types]]> + calling_method_id]]> + + + + + $function_id + + + + + $function_id + + + + + $function_id + + + + + output_path]]> + $parent_issue_type + + + + + other_references]]> + taint_trace]]> + + + + + + other_references]]> + taint_trace]]> + + + + + + taint_trace]]> + @@ -477,6 +2225,19 @@ traverse + + + $this_var_id + + + + + !$namespace + $namespace + $namespace + + + classOrInterfaceExists @@ -495,6 +2256,9 @@ $value + + + @@ -503,6 +2267,10 @@ replace replace + + $params + $params + @@ -513,6 +2281,9 @@ type_params[1]]]> + + !($container_type_params_covariant[$offset] ?? true) + @@ -528,6 +2299,10 @@ replace + + !$namespace + $namespace + @@ -540,6 +2315,12 @@ value_param]]> + + + !$intersection + !$intersection + + replace @@ -550,6 +2331,17 @@ __construct + + + !$intersection + !$intersection + + + + + !$intersection + + TList @@ -591,6 +2383,18 @@ type_param]]> + + + !$namespace + $namespace + + + + + !$intersection + $intersection + + TList @@ -604,12 +2408,21 @@ replace replace + + !$intersection + !$intersection + replace + + + !$intersection + + replace @@ -620,6 +2433,11 @@ replace + + + extra_types]]> + + $allow_mutations @@ -630,11 +2448,24 @@ $initialized_class $reference_free + + + $const_name + + + + $array_key_offset + $failed_reconciliation + + + ')]]> + + @@ -670,10 +2501,41 @@ hasLowercaseString hasLowercaseString - - - - - + + !$php_type + exact_id]]> + id]]> + exact_id]]> + exact_id]]> + id]]> + id]]> + + + + + + + + + + + $level + $php_version + + + + + + + + + + + $param_type_1 + $param_type_2 + $param_type_3 + $param_type_4 + $return_type + From 645e59ee538141ff7706e685220f3a7ad8e9ef2c Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 15 Jan 2024 17:36:32 +0100 Subject: [PATCH 54/63] cs-fix --- src/Psalm/Aliases.php | 2 ++ .../Expression/Call/FunctionCallReturnTypeFetcher.php | 1 - .../Statements/Expression/Call/NamedFunctionCallHandler.php | 2 +- src/Psalm/Internal/MethodIdentifier.php | 2 +- src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php | 2 -- src/Psalm/Internal/Type/TypeParser.php | 1 - src/Psalm/IssueBuffer.php | 1 + 7 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Psalm/Aliases.php b/src/Psalm/Aliases.php index 58f7eccc63c..9471120d03e 100644 --- a/src/Psalm/Aliases.php +++ b/src/Psalm/Aliases.php @@ -10,6 +10,8 @@ final class Aliases { use UnserializeMemoryUsageSuppressionTrait; + public ?int $namespace_first_stmt_start = null; + public ?int $uses_start = null; public ?int $uses_end = null; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php index 4374ca7cd78..b7de2fd223c 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php @@ -48,7 +48,6 @@ use function explode; use function in_array; use function str_contains; -use function str_ends_with; use function strlen; use function strtolower; use function substr; diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NamedFunctionCallHandler.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NamedFunctionCallHandler.php index 1e608a427c4..80c780de50b 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NamedFunctionCallHandler.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NamedFunctionCallHandler.php @@ -55,8 +55,8 @@ use function in_array; use function is_numeric; use function is_string; -use function str_starts_with; use function preg_match; +use function str_starts_with; use function strpos; use function strtolower; diff --git a/src/Psalm/Internal/MethodIdentifier.php b/src/Psalm/Internal/MethodIdentifier.php index b75b4d5209e..b50a9f9f316 100644 --- a/src/Psalm/Internal/MethodIdentifier.php +++ b/src/Psalm/Internal/MethodIdentifier.php @@ -6,8 +6,8 @@ use InvalidArgumentException; use Psalm\Storage\ImmutableNonCloneableTrait; -use Stringable; use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; +use Stringable; use function explode; use function is_string; diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php index a4d6c50f3ca..9ccbd8e6c61 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php @@ -29,9 +29,7 @@ use function dirname; use function explode; use function in_array; -use function preg_match; use function str_contains; -use function strpos; use function strtolower; use function substr; diff --git a/src/Psalm/Internal/Type/TypeParser.php b/src/Psalm/Internal/Type/TypeParser.php index 99865754b6e..3f344916582 100644 --- a/src/Psalm/Internal/Type/TypeParser.php +++ b/src/Psalm/Internal/Type/TypeParser.php @@ -89,7 +89,6 @@ use function end; use function explode; use function filter_var; -use function get_class; use function in_array; use function is_int; use function is_numeric; diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index 57a4f9c6f83..dd35480c48f 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -56,6 +56,7 @@ use function explode; use function file_put_contents; use function fwrite; +use function get_class; use function implode; use function in_array; use function is_dir; From a3a13241a76d19e7e7f0f51bef973f8c9266d594 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Wed, 17 Jan 2024 12:41:58 +0100 Subject: [PATCH 55/63] fix baseline somehow incorrect paths --- psalm-baseline.xml | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 85f358308e2..ed55df4536a 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,16 +1,16 @@ - + mapper]]> - + $items - + $returnType attrGroups]]> @@ -24,7 +24,7 @@ - + $returnType attrGroups]]> @@ -36,39 +36,39 @@ uses]]> - + $items - + $parts - + $conds - + $parts $parts $parts - + $stmts - + $stmts - + $returnType attrGroups]]> @@ -79,7 +79,7 @@ stmts]]> - + attrGroups]]> extends]]> @@ -88,27 +88,27 @@ stmts]]> - + $stmts - + $stmts - + $stmts - + $stmts - + cond]]> init]]> @@ -116,14 +116,14 @@ stmts]]> - + byRef]]> keyVar]]> stmts]]> - + $returnType attrGroups]]> @@ -133,42 +133,42 @@ stmts]]> - + else]]> elseifs]]> stmts]]> - + attrGroups]]> extends]]> stmts]]> - + $stmts - + attrGroups]]> stmts]]> - + $stmts - + $stmts - + static::getDefaultDescription() static::getDefaultDescription() From 0504394e8b72733aa1e399bf0dba1547bbbccb8b Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 17 Jan 2024 12:52:36 +0100 Subject: [PATCH 56/63] Fixup --- src/Psalm/Internal/PhpTraverser/CustomTraverser.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Psalm/Internal/PhpTraverser/CustomTraverser.php b/src/Psalm/Internal/PhpTraverser/CustomTraverser.php index f1e2673572d..397601d4e59 100644 --- a/src/Psalm/Internal/PhpTraverser/CustomTraverser.php +++ b/src/Psalm/Internal/PhpTraverser/CustomTraverser.php @@ -29,7 +29,7 @@ public function __construct() * @param Node $node node to traverse * @return Node Result of traversal (may be original node or new one) */ - protected function traverseNode(Node $node): Node + protected function traverseNode(Node $node): void { foreach ($node->getSubNodeNames() as $name) { $subNode = &$node->$name; @@ -60,7 +60,7 @@ protected function traverseNode(Node $node): Node } if ($traverseChildren) { - $subNode = $this->traverseNode($subNode); + $this->traverseNode($subNode); if ($this->stopTraversal) { break; } @@ -88,8 +88,6 @@ protected function traverseNode(Node $node): Node } } } - - return $node; } /** From 4e5e30633bd4798da15d9f2bc51b59fc2fba068b Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 17 Jan 2024 13:29:08 +0100 Subject: [PATCH 57/63] Fixup --- src/Psalm/Internal/Analyzer/ClosureAnalyzer.php | 2 ++ src/Psalm/Internal/Analyzer/FunctionAnalyzer.php | 2 ++ src/Psalm/Internal/Analyzer/MethodAnalyzer.php | 2 ++ src/Psalm/Storage/Assertion/Any.php | 2 ++ src/Psalm/Storage/Assertion/ArrayKeyDoesNotExist.php | 2 ++ src/Psalm/Storage/Assertion/ArrayKeyExists.php | 2 ++ src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php | 2 ++ src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php | 2 ++ src/Psalm/Storage/Assertion/DoesNotHaveMethod.php | 2 ++ src/Psalm/Storage/Assertion/Empty_.php | 2 ++ src/Psalm/Storage/Assertion/Falsy.php | 2 ++ src/Psalm/Storage/Assertion/HasArrayKey.php | 2 ++ src/Psalm/Storage/Assertion/HasAtLeastCount.php | 2 ++ src/Psalm/Storage/Assertion/HasExactCount.php | 2 ++ src/Psalm/Storage/Assertion/HasIntOrStringArrayAccess.php | 2 ++ src/Psalm/Storage/Assertion/HasMethod.php | 2 ++ src/Psalm/Storage/Assertion/HasStringArrayAccess.php | 2 ++ src/Psalm/Storage/Assertion/InArray.php | 2 ++ src/Psalm/Storage/Assertion/IsAClass.php | 2 ++ src/Psalm/Storage/Assertion/IsClassEqual.php | 2 ++ src/Psalm/Storage/Assertion/IsClassNotEqual.php | 2 ++ src/Psalm/Storage/Assertion/IsCountable.php | 2 ++ src/Psalm/Storage/Assertion/IsEqualIsset.php | 2 ++ src/Psalm/Storage/Assertion/IsGreaterThan.php | 2 ++ src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php | 2 ++ src/Psalm/Storage/Assertion/IsIdentical.php | 2 ++ src/Psalm/Storage/Assertion/IsIsset.php | 2 ++ src/Psalm/Storage/Assertion/IsLessThan.php | 2 ++ src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php | 2 ++ src/Psalm/Storage/Assertion/IsLooselyEqual.php | 2 ++ src/Psalm/Storage/Assertion/IsNotAClass.php | 2 ++ src/Psalm/Storage/Assertion/IsNotCountable.php | 2 ++ src/Psalm/Storage/Assertion/IsNotIdentical.php | 2 ++ src/Psalm/Storage/Assertion/IsNotIsset.php | 2 ++ src/Psalm/Storage/Assertion/IsNotLooselyEqual.php | 2 ++ src/Psalm/Storage/Assertion/IsNotType.php | 2 ++ src/Psalm/Storage/Assertion/IsType.php | 2 ++ src/Psalm/Storage/Assertion/NestedAssertions.php | 2 ++ src/Psalm/Storage/Assertion/NonEmpty.php | 2 ++ src/Psalm/Storage/Assertion/NonEmptyCountable.php | 2 ++ src/Psalm/Storage/Assertion/NotInArray.php | 2 ++ src/Psalm/Storage/Assertion/NotNestedAssertions.php | 2 ++ src/Psalm/Storage/Assertion/NotNonEmptyCountable.php | 2 ++ src/Psalm/Storage/Assertion/Truthy.php | 2 ++ src/Psalm/Storage/FunctionStorage.php | 1 + src/Psalm/Storage/MethodStorage.php | 1 + src/Psalm/Type/Atomic/Scalar.php | 2 ++ src/Psalm/Type/Atomic/TArray.php | 2 ++ src/Psalm/Type/Atomic/TCallable.php | 2 ++ src/Psalm/Type/Atomic/TClassConstant.php | 2 ++ src/Psalm/Type/Atomic/TClassStringMap.php | 2 ++ src/Psalm/Type/Atomic/TClosedResource.php | 2 ++ src/Psalm/Type/Atomic/TConditional.php | 2 ++ src/Psalm/Type/Atomic/TIterable.php | 2 ++ src/Psalm/Type/Atomic/TKeyedArray.php | 2 ++ src/Psalm/Type/Atomic/TMixed.php | 2 ++ src/Psalm/Type/Atomic/TNever.php | 2 ++ src/Psalm/Type/Atomic/TNull.php | 2 ++ src/Psalm/Type/Atomic/TObject.php | 2 ++ src/Psalm/Type/Atomic/TPropertiesOf.php | 2 ++ src/Psalm/Type/Atomic/TResource.php | 2 ++ src/Psalm/Type/Atomic/TTemplateIndexedAccess.php | 2 ++ src/Psalm/Type/Atomic/TTemplateKeyOf.php | 2 ++ src/Psalm/Type/Atomic/TTemplateParam.php | 2 ++ src/Psalm/Type/Atomic/TTemplatePropertiesOf.php | 2 ++ src/Psalm/Type/Atomic/TTemplateValueOf.php | 2 ++ src/Psalm/Type/Atomic/TTypeAlias.php | 2 ++ src/Psalm/Type/Atomic/TValueOf.php | 2 ++ src/Psalm/Type/Atomic/TVoid.php | 2 ++ 69 files changed, 136 insertions(+) diff --git a/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php b/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php index afe483caf49..0149e800c92 100644 --- a/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php @@ -14,6 +14,7 @@ use Psalm\Issue\PossiblyUndefinedVariable; use Psalm\Issue\UndefinedVariable; use Psalm\IssueBuffer; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type; use Psalm\Type\Atomic\TNamedObject; use Psalm\Type\Union; @@ -30,6 +31,7 @@ */ final class ClosureAnalyzer extends FunctionLikeAnalyzer { + use UnserializeMemoryUsageSuppressionTrait; /** * @param PhpParser\Node\Expr\Closure|PhpParser\Node\Expr\ArrowFunction $function */ diff --git a/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php b/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php index bcf1395909a..3c8a293b0be 100644 --- a/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php @@ -7,6 +7,7 @@ use PhpParser; use Psalm\Config; use Psalm\Context; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use UnexpectedValueException; use function is_string; @@ -18,6 +19,7 @@ */ final class FunctionAnalyzer extends FunctionLikeAnalyzer { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(PhpParser\Node\Stmt\Function_ $function, SourceAnalyzer $source) { $codebase = $source->getCodebase(); diff --git a/src/Psalm/Internal/Analyzer/MethodAnalyzer.php b/src/Psalm/Internal/Analyzer/MethodAnalyzer.php index 3758cd06bef..1c68bee7a7b 100644 --- a/src/Psalm/Internal/Analyzer/MethodAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/MethodAnalyzer.php @@ -20,6 +20,7 @@ use Psalm\StatementsSource; use Psalm\Storage\ClassLikeStorage; use Psalm\Storage\MethodStorage; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use UnexpectedValueException; use function in_array; @@ -31,6 +32,7 @@ */ final class MethodAnalyzer extends FunctionLikeAnalyzer { + use UnserializeMemoryUsageSuppressionTrait; // https://github.com/php/php-src/blob/a83923044c48982c80804ae1b45e761c271966d3/Zend/zend_enum.c#L77-L95 private const FORBIDDEN_ENUM_METHODS = [ '__construct', diff --git a/src/Psalm/Storage/Assertion/Any.php b/src/Psalm/Storage/Assertion/Any.php index ad9e4e88c13..b8e3e3e584f 100644 --- a/src/Psalm/Storage/Assertion/Any.php +++ b/src/Psalm/Storage/Assertion/Any.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class Any extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return $this; diff --git a/src/Psalm/Storage/Assertion/ArrayKeyDoesNotExist.php b/src/Psalm/Storage/Assertion/ArrayKeyDoesNotExist.php index 73f0e3e9cea..53e7cdffb72 100644 --- a/src/Psalm/Storage/Assertion/ArrayKeyDoesNotExist.php +++ b/src/Psalm/Storage/Assertion/ArrayKeyDoesNotExist.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class ArrayKeyDoesNotExist extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new ArrayKeyExists(); diff --git a/src/Psalm/Storage/Assertion/ArrayKeyExists.php b/src/Psalm/Storage/Assertion/ArrayKeyExists.php index aab0e3f01db..c21d4428e47 100644 --- a/src/Psalm/Storage/Assertion/ArrayKeyExists.php +++ b/src/Psalm/Storage/Assertion/ArrayKeyExists.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class ArrayKeyExists extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new ArrayKeyDoesNotExist(); diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php b/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php index 01e55a42192..b37c997134a 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveAtLeastCount.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class DoesNotHaveAtLeastCount extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; /** @param positive-int $count */ public function __construct(public readonly int $count) { diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php b/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php index 125b0bd8f1e..e557085cd3f 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveExactCount.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class DoesNotHaveExactCount extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; /** @param positive-int $count */ public function __construct(public readonly int $count) { diff --git a/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php b/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php index 72b5e0e20ba..4a6a891c46e 100644 --- a/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php +++ b/src/Psalm/Storage/Assertion/DoesNotHaveMethod.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class DoesNotHaveMethod extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly string $method) { } diff --git a/src/Psalm/Storage/Assertion/Empty_.php b/src/Psalm/Storage/Assertion/Empty_.php index 344b99d6b08..53bca41fada 100644 --- a/src/Psalm/Storage/Assertion/Empty_.php +++ b/src/Psalm/Storage/Assertion/Empty_.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class Empty_ extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new NonEmpty(); diff --git a/src/Psalm/Storage/Assertion/Falsy.php b/src/Psalm/Storage/Assertion/Falsy.php index d758b8352ee..5ac93ba421e 100644 --- a/src/Psalm/Storage/Assertion/Falsy.php +++ b/src/Psalm/Storage/Assertion/Falsy.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class Falsy extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new Truthy(); diff --git a/src/Psalm/Storage/Assertion/HasArrayKey.php b/src/Psalm/Storage/Assertion/HasArrayKey.php index 1326f09510e..8b0bb509651 100644 --- a/src/Psalm/Storage/Assertion/HasArrayKey.php +++ b/src/Psalm/Storage/Assertion/HasArrayKey.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use UnexpectedValueException; /** @@ -12,6 +13,7 @@ */ final class HasArrayKey extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly string $key) { } diff --git a/src/Psalm/Storage/Assertion/HasAtLeastCount.php b/src/Psalm/Storage/Assertion/HasAtLeastCount.php index 479d5191866..98581348f93 100644 --- a/src/Psalm/Storage/Assertion/HasAtLeastCount.php +++ b/src/Psalm/Storage/Assertion/HasAtLeastCount.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class HasAtLeastCount extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; /** @param positive-int $count */ public function __construct(public readonly int $count) { diff --git a/src/Psalm/Storage/Assertion/HasExactCount.php b/src/Psalm/Storage/Assertion/HasExactCount.php index 9bb5b8edda5..8f28be407fb 100644 --- a/src/Psalm/Storage/Assertion/HasExactCount.php +++ b/src/Psalm/Storage/Assertion/HasExactCount.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class HasExactCount extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; /** @param positive-int $count */ public function __construct(public readonly int $count) { diff --git a/src/Psalm/Storage/Assertion/HasIntOrStringArrayAccess.php b/src/Psalm/Storage/Assertion/HasIntOrStringArrayAccess.php index db401486ad7..39be9c6d610 100644 --- a/src/Psalm/Storage/Assertion/HasIntOrStringArrayAccess.php +++ b/src/Psalm/Storage/Assertion/HasIntOrStringArrayAccess.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use UnexpectedValueException; /** @@ -12,6 +13,7 @@ */ final class HasIntOrStringArrayAccess extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { throw new UnexpectedValueException('This should never be called'); diff --git a/src/Psalm/Storage/Assertion/HasMethod.php b/src/Psalm/Storage/Assertion/HasMethod.php index 87e090cadcb..ed994ce149e 100644 --- a/src/Psalm/Storage/Assertion/HasMethod.php +++ b/src/Psalm/Storage/Assertion/HasMethod.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class HasMethod extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly string $method) { } diff --git a/src/Psalm/Storage/Assertion/HasStringArrayAccess.php b/src/Psalm/Storage/Assertion/HasStringArrayAccess.php index 1d2b519b72a..3a8e65a2813 100644 --- a/src/Psalm/Storage/Assertion/HasStringArrayAccess.php +++ b/src/Psalm/Storage/Assertion/HasStringArrayAccess.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use UnexpectedValueException; /** @@ -12,6 +13,7 @@ */ final class HasStringArrayAccess extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { throw new UnexpectedValueException('This should never be called'); diff --git a/src/Psalm/Storage/Assertion/InArray.php b/src/Psalm/Storage/Assertion/InArray.php index 021f18f1d58..6c88a4f3d66 100644 --- a/src/Psalm/Storage/Assertion/InArray.php +++ b/src/Psalm/Storage/Assertion/InArray.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Union; /** @@ -12,6 +13,7 @@ */ final class InArray extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly Union $type) { } diff --git a/src/Psalm/Storage/Assertion/IsAClass.php b/src/Psalm/Storage/Assertion/IsAClass.php index 1909c7eb000..905302771c0 100644 --- a/src/Psalm/Storage/Assertion/IsAClass.php +++ b/src/Psalm/Storage/Assertion/IsAClass.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -12,6 +13,7 @@ */ final class IsAClass extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; /** @param Atomic\TTemplateParamClass|Atomic\TNamedObject $type */ public function __construct(public readonly Atomic $type, public readonly bool $allow_string) { diff --git a/src/Psalm/Storage/Assertion/IsClassEqual.php b/src/Psalm/Storage/Assertion/IsClassEqual.php index fc117d1506a..88e8d1527c8 100644 --- a/src/Psalm/Storage/Assertion/IsClassEqual.php +++ b/src/Psalm/Storage/Assertion/IsClassEqual.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsClassEqual extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly string $type) { } diff --git a/src/Psalm/Storage/Assertion/IsClassNotEqual.php b/src/Psalm/Storage/Assertion/IsClassNotEqual.php index e5ccaa42130..d94fb6246ef 100644 --- a/src/Psalm/Storage/Assertion/IsClassNotEqual.php +++ b/src/Psalm/Storage/Assertion/IsClassNotEqual.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsClassNotEqual extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly string $type) { } diff --git a/src/Psalm/Storage/Assertion/IsCountable.php b/src/Psalm/Storage/Assertion/IsCountable.php index 552d7904ca4..f1f213df5b2 100644 --- a/src/Psalm/Storage/Assertion/IsCountable.php +++ b/src/Psalm/Storage/Assertion/IsCountable.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsCountable extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new IsNotCountable(true); diff --git a/src/Psalm/Storage/Assertion/IsEqualIsset.php b/src/Psalm/Storage/Assertion/IsEqualIsset.php index ce2a2f27901..7cc82cacb8c 100644 --- a/src/Psalm/Storage/Assertion/IsEqualIsset.php +++ b/src/Psalm/Storage/Assertion/IsEqualIsset.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsEqualIsset extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new Any(); diff --git a/src/Psalm/Storage/Assertion/IsGreaterThan.php b/src/Psalm/Storage/Assertion/IsGreaterThan.php index fa3087475e3..a4d4fb153f8 100644 --- a/src/Psalm/Storage/Assertion/IsGreaterThan.php +++ b/src/Psalm/Storage/Assertion/IsGreaterThan.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsGreaterThan extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly int $value) { } diff --git a/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php b/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php index 3d4dde1bd92..295ad5eb444 100644 --- a/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php +++ b/src/Psalm/Storage/Assertion/IsGreaterThanOrEqualTo.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsGreaterThanOrEqualTo extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly int $value) { } diff --git a/src/Psalm/Storage/Assertion/IsIdentical.php b/src/Psalm/Storage/Assertion/IsIdentical.php index de3c3db39f5..86f5212407a 100644 --- a/src/Psalm/Storage/Assertion/IsIdentical.php +++ b/src/Psalm/Storage/Assertion/IsIdentical.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -12,6 +13,7 @@ */ final class IsIdentical extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsIsset.php b/src/Psalm/Storage/Assertion/IsIsset.php index be7c11bedb0..01fc40467e7 100644 --- a/src/Psalm/Storage/Assertion/IsIsset.php +++ b/src/Psalm/Storage/Assertion/IsIsset.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsIsset extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new IsNotIsset(); diff --git a/src/Psalm/Storage/Assertion/IsLessThan.php b/src/Psalm/Storage/Assertion/IsLessThan.php index 508b3f8031c..5587ad32ce4 100644 --- a/src/Psalm/Storage/Assertion/IsLessThan.php +++ b/src/Psalm/Storage/Assertion/IsLessThan.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsLessThan extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly int $value) { } diff --git a/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php b/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php index d6934334e71..2ef344bf3c1 100644 --- a/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php +++ b/src/Psalm/Storage/Assertion/IsLessThanOrEqualTo.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsLessThanOrEqualTo extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly int $value) { } diff --git a/src/Psalm/Storage/Assertion/IsLooselyEqual.php b/src/Psalm/Storage/Assertion/IsLooselyEqual.php index a5d5b6ac4ed..4fd2aa367fb 100644 --- a/src/Psalm/Storage/Assertion/IsLooselyEqual.php +++ b/src/Psalm/Storage/Assertion/IsLooselyEqual.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -12,6 +13,7 @@ */ final class IsLooselyEqual extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsNotAClass.php b/src/Psalm/Storage/Assertion/IsNotAClass.php index 80303df369c..d710eb7eea7 100644 --- a/src/Psalm/Storage/Assertion/IsNotAClass.php +++ b/src/Psalm/Storage/Assertion/IsNotAClass.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -12,6 +13,7 @@ */ final class IsNotAClass extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; /** @param Atomic\TTemplateParamClass|Atomic\TNamedObject $type */ public function __construct(public readonly Atomic $type, public readonly bool $allow_string) { diff --git a/src/Psalm/Storage/Assertion/IsNotCountable.php b/src/Psalm/Storage/Assertion/IsNotCountable.php index 5f11cf6df6b..bf9b4db9a04 100644 --- a/src/Psalm/Storage/Assertion/IsNotCountable.php +++ b/src/Psalm/Storage/Assertion/IsNotCountable.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsNotCountable extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly bool $is_negatable) { } diff --git a/src/Psalm/Storage/Assertion/IsNotIdentical.php b/src/Psalm/Storage/Assertion/IsNotIdentical.php index 11c482d1c04..22b6e7c02d1 100644 --- a/src/Psalm/Storage/Assertion/IsNotIdentical.php +++ b/src/Psalm/Storage/Assertion/IsNotIdentical.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -12,6 +13,7 @@ */ final class IsNotIdentical extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsNotIsset.php b/src/Psalm/Storage/Assertion/IsNotIsset.php index d73aa64b68d..890b3fdb1e1 100644 --- a/src/Psalm/Storage/Assertion/IsNotIsset.php +++ b/src/Psalm/Storage/Assertion/IsNotIsset.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class IsNotIsset extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new IsIsset(); diff --git a/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php b/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php index bb8d4ee7d0e..63a5a78f8c4 100644 --- a/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php +++ b/src/Psalm/Storage/Assertion/IsNotLooselyEqual.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -12,6 +13,7 @@ */ final class IsNotLooselyEqual extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsNotType.php b/src/Psalm/Storage/Assertion/IsNotType.php index 1d51e037017..28a769ca26e 100644 --- a/src/Psalm/Storage/Assertion/IsNotType.php +++ b/src/Psalm/Storage/Assertion/IsNotType.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -12,6 +13,7 @@ */ final class IsNotType extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/IsType.php b/src/Psalm/Storage/Assertion/IsType.php index 70920806743..0bc6c63c9a1 100644 --- a/src/Psalm/Storage/Assertion/IsType.php +++ b/src/Psalm/Storage/Assertion/IsType.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -12,6 +13,7 @@ */ final class IsType extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly Atomic $type) { } diff --git a/src/Psalm/Storage/Assertion/NestedAssertions.php b/src/Psalm/Storage/Assertion/NestedAssertions.php index 353807d2401..7d6f405caa2 100644 --- a/src/Psalm/Storage/Assertion/NestedAssertions.php +++ b/src/Psalm/Storage/Assertion/NestedAssertions.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use function json_encode; @@ -15,6 +16,7 @@ */ final class NestedAssertions extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; /** @param array>> $assertions */ public function __construct(public readonly array $assertions) { diff --git a/src/Psalm/Storage/Assertion/NonEmpty.php b/src/Psalm/Storage/Assertion/NonEmpty.php index ac208f4d2a3..159da72e798 100644 --- a/src/Psalm/Storage/Assertion/NonEmpty.php +++ b/src/Psalm/Storage/Assertion/NonEmpty.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class NonEmpty extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new Empty_(); diff --git a/src/Psalm/Storage/Assertion/NonEmptyCountable.php b/src/Psalm/Storage/Assertion/NonEmptyCountable.php index a36bffdd2a6..8ab74c5bfce 100644 --- a/src/Psalm/Storage/Assertion/NonEmptyCountable.php +++ b/src/Psalm/Storage/Assertion/NonEmptyCountable.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class NonEmptyCountable extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public readonly bool $is_negatable) { } diff --git a/src/Psalm/Storage/Assertion/NotInArray.php b/src/Psalm/Storage/Assertion/NotInArray.php index 17c385f8825..fd47839f84e 100644 --- a/src/Psalm/Storage/Assertion/NotInArray.php +++ b/src/Psalm/Storage/Assertion/NotInArray.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Union; /** @@ -12,6 +13,7 @@ */ final class NotInArray extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function __construct( public readonly Union $type, ) { diff --git a/src/Psalm/Storage/Assertion/NotNestedAssertions.php b/src/Psalm/Storage/Assertion/NotNestedAssertions.php index 4ca457dcf02..acf8696b1ea 100644 --- a/src/Psalm/Storage/Assertion/NotNestedAssertions.php +++ b/src/Psalm/Storage/Assertion/NotNestedAssertions.php @@ -5,6 +5,7 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use function json_encode; @@ -15,6 +16,7 @@ */ final class NotNestedAssertions extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; /** @param array>> $assertions */ public function __construct(public readonly array $assertions) { diff --git a/src/Psalm/Storage/Assertion/NotNonEmptyCountable.php b/src/Psalm/Storage/Assertion/NotNonEmptyCountable.php index 1306167789c..b9eb20f26b5 100644 --- a/src/Psalm/Storage/Assertion/NotNonEmptyCountable.php +++ b/src/Psalm/Storage/Assertion/NotNonEmptyCountable.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class NotNonEmptyCountable extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new NonEmptyCountable(true); diff --git a/src/Psalm/Storage/Assertion/Truthy.php b/src/Psalm/Storage/Assertion/Truthy.php index 35ec5d32e3c..c1e62224f2c 100644 --- a/src/Psalm/Storage/Assertion/Truthy.php +++ b/src/Psalm/Storage/Assertion/Truthy.php @@ -5,12 +5,14 @@ namespace Psalm\Storage\Assertion; use Psalm\Storage\Assertion; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; /** * @psalm-immutable */ final class Truthy extends Assertion { + use UnserializeMemoryUsageSuppressionTrait; public function getNegation(): Assertion { return new Falsy(); diff --git a/src/Psalm/Storage/FunctionStorage.php b/src/Psalm/Storage/FunctionStorage.php index f9c9dcfeeb2..043bb1832ba 100644 --- a/src/Psalm/Storage/FunctionStorage.php +++ b/src/Psalm/Storage/FunctionStorage.php @@ -6,6 +6,7 @@ final class FunctionStorage extends FunctionLikeStorage { + use UnserializeMemoryUsageSuppressionTrait; /** @var array */ public array $byref_uses = []; } diff --git a/src/Psalm/Storage/MethodStorage.php b/src/Psalm/Storage/MethodStorage.php index c6ebc2d8aab..3dd5986db9a 100644 --- a/src/Psalm/Storage/MethodStorage.php +++ b/src/Psalm/Storage/MethodStorage.php @@ -8,6 +8,7 @@ final class MethodStorage extends FunctionLikeStorage { + use UnserializeMemoryUsageSuppressionTrait; public bool $is_static = false; public int $visibility = 0; diff --git a/src/Psalm/Type/Atomic/Scalar.php b/src/Psalm/Type/Atomic/Scalar.php index 739bb9bb514..c4597dffbe7 100644 --- a/src/Psalm/Type/Atomic/Scalar.php +++ b/src/Psalm/Type/Atomic/Scalar.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -11,6 +12,7 @@ */ abstract class Scalar extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function canBeFullyExpressedInPhp(int $analysis_php_version_id): bool { return true; diff --git a/src/Psalm/Type/Atomic/TArray.php b/src/Psalm/Type/Atomic/TArray.php index 0aee4453e40..37cf0bc694f 100644 --- a/src/Psalm/Type/Atomic/TArray.php +++ b/src/Psalm/Type/Atomic/TArray.php @@ -7,6 +7,7 @@ use Psalm\Codebase; use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Internal\Type\TemplateResult; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -19,6 +20,7 @@ */ class TArray extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; /** * @use GenericTrait */ diff --git a/src/Psalm/Type/Atomic/TCallable.php b/src/Psalm/Type/Atomic/TCallable.php index 90fb430a291..cbf8141d1db 100644 --- a/src/Psalm/Type/Atomic/TCallable.php +++ b/src/Psalm/Type/Atomic/TCallable.php @@ -8,6 +8,7 @@ use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Internal\Type\TemplateResult; use Psalm\Storage\FunctionLikeParameter; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -18,6 +19,7 @@ */ final class TCallable extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; use CallableTrait; public string $value; diff --git a/src/Psalm/Type/Atomic/TClassConstant.php b/src/Psalm/Type/Atomic/TClassConstant.php index 21e8c0a25a5..6acc150a2ec 100644 --- a/src/Psalm/Type/Atomic/TClassConstant.php +++ b/src/Psalm/Type/Atomic/TClassConstant.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type; use Psalm\Type\Atomic; @@ -14,6 +15,7 @@ */ final class TClassConstant extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function __construct( public string $fq_classlike_name, public string $const_name, diff --git a/src/Psalm/Type/Atomic/TClassStringMap.php b/src/Psalm/Type/Atomic/TClassStringMap.php index aae43a24b99..e64f0c60313 100644 --- a/src/Psalm/Type/Atomic/TClassStringMap.php +++ b/src/Psalm/Type/Atomic/TClassStringMap.php @@ -9,6 +9,7 @@ use Psalm\Internal\Type\TemplateInferredTypeReplacer; use Psalm\Internal\Type\TemplateResult; use Psalm\Internal\Type\TemplateStandinTypeReplacer; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -21,6 +22,7 @@ */ final class TClassStringMap extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; /** * Constructs a new instance of a list */ diff --git a/src/Psalm/Type/Atomic/TClosedResource.php b/src/Psalm/Type/Atomic/TClosedResource.php index 3bde7d5508e..ffdf3697f27 100644 --- a/src/Psalm/Type/Atomic/TClosedResource.php +++ b/src/Psalm/Type/Atomic/TClosedResource.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -13,6 +14,7 @@ */ final class TClosedResource extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function getKey(bool $include_extra = true): string { return 'closed-resource'; diff --git a/src/Psalm/Type/Atomic/TConditional.php b/src/Psalm/Type/Atomic/TConditional.php index 4d6fc9f9afb..6509a574724 100644 --- a/src/Psalm/Type/Atomic/TConditional.php +++ b/src/Psalm/Type/Atomic/TConditional.php @@ -7,6 +7,7 @@ use Psalm\Codebase; use Psalm\Internal\Type\TemplateInferredTypeReplacer; use Psalm\Internal\Type\TemplateResult; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -17,6 +18,7 @@ */ final class TConditional extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function __construct( public string $param_name, public string $defining_class, diff --git a/src/Psalm/Type/Atomic/TIterable.php b/src/Psalm/Type/Atomic/TIterable.php index a9b9ae988a4..52878f27caa 100644 --- a/src/Psalm/Type/Atomic/TIterable.php +++ b/src/Psalm/Type/Atomic/TIterable.php @@ -7,6 +7,7 @@ use Psalm\Codebase; use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Internal\Type\TemplateResult; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -22,6 +23,7 @@ */ final class TIterable extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; use HasIntersectionTrait; /** * @use GenericTrait diff --git a/src/Psalm/Type/Atomic/TKeyedArray.php b/src/Psalm/Type/Atomic/TKeyedArray.php index 9a7da6213f0..189784ec3f0 100644 --- a/src/Psalm/Type/Atomic/TKeyedArray.php +++ b/src/Psalm/Type/Atomic/TKeyedArray.php @@ -10,6 +10,7 @@ use Psalm\Internal\Type\TemplateResult; use Psalm\Internal\Type\TemplateStandinTypeReplacer; use Psalm\Internal\Type\TypeCombiner; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -32,6 +33,7 @@ */ class TKeyedArray extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; /** * If the shape has fallback params then they are here * diff --git a/src/Psalm/Type/Atomic/TMixed.php b/src/Psalm/Type/Atomic/TMixed.php index 579c8a34737..a1019583718 100644 --- a/src/Psalm/Type/Atomic/TMixed.php +++ b/src/Psalm/Type/Atomic/TMixed.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -13,6 +14,7 @@ */ class TMixed extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public bool $from_loop_isset = false, bool $from_docblock = false) { parent::__construct($from_docblock); diff --git a/src/Psalm/Type/Atomic/TNever.php b/src/Psalm/Type/Atomic/TNever.php index a9918aeb8e2..6121a752b05 100644 --- a/src/Psalm/Type/Atomic/TNever.php +++ b/src/Psalm/Type/Atomic/TNever.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -14,6 +15,7 @@ */ final class TNever extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function getKey(bool $include_extra = true): string { return 'never'; diff --git a/src/Psalm/Type/Atomic/TNull.php b/src/Psalm/Type/Atomic/TNull.php index 4f8df9abe72..e8ee44fef9a 100644 --- a/src/Psalm/Type/Atomic/TNull.php +++ b/src/Psalm/Type/Atomic/TNull.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -13,6 +14,7 @@ */ final class TNull extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function getKey(bool $include_extra = true): string { return 'null'; diff --git a/src/Psalm/Type/Atomic/TObject.php b/src/Psalm/Type/Atomic/TObject.php index 14b5036a75e..e6c4556aa85 100644 --- a/src/Psalm/Type/Atomic/TObject.php +++ b/src/Psalm/Type/Atomic/TObject.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -13,6 +14,7 @@ */ class TObject extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function getKey(bool $include_extra = true): string { return 'object'; diff --git a/src/Psalm/Type/Atomic/TPropertiesOf.php b/src/Psalm/Type/Atomic/TPropertiesOf.php index 7724143c1b9..c9df9d0bd32 100644 --- a/src/Psalm/Type/Atomic/TPropertiesOf.php +++ b/src/Psalm/Type/Atomic/TPropertiesOf.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -15,6 +16,7 @@ */ final class TPropertiesOf extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; // These should match the values of // `Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_*`, as they are // used to compared against properties visibililty. diff --git a/src/Psalm/Type/Atomic/TResource.php b/src/Psalm/Type/Atomic/TResource.php index b01a0987bde..f67527df27a 100644 --- a/src/Psalm/Type/Atomic/TResource.php +++ b/src/Psalm/Type/Atomic/TResource.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -13,6 +14,7 @@ */ final class TResource extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function getKey(bool $include_extra = true): string { return 'resource'; diff --git a/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php b/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php index c572c185234..102b8c0e5af 100644 --- a/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php +++ b/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -11,6 +12,7 @@ */ final class TTemplateIndexedAccess extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function __construct( public string $array_param_name, public string $offset_param_name, diff --git a/src/Psalm/Type/Atomic/TTemplateKeyOf.php b/src/Psalm/Type/Atomic/TTemplateKeyOf.php index 4773dc9d4df..c6a728c88a2 100644 --- a/src/Psalm/Type/Atomic/TTemplateKeyOf.php +++ b/src/Psalm/Type/Atomic/TTemplateKeyOf.php @@ -7,6 +7,7 @@ use Psalm\Codebase; use Psalm\Internal\Type\TemplateInferredTypeReplacer; use Psalm\Internal\Type\TemplateResult; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -17,6 +18,7 @@ */ final class TTemplateKeyOf extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function __construct( public string $param_name, public string $defining_class, diff --git a/src/Psalm/Type/Atomic/TTemplateParam.php b/src/Psalm/Type/Atomic/TTemplateParam.php index 9f618b3090b..84169899a52 100644 --- a/src/Psalm/Type/Atomic/TTemplateParam.php +++ b/src/Psalm/Type/Atomic/TTemplateParam.php @@ -6,6 +6,7 @@ use Psalm\Codebase; use Psalm\Internal\Type\TemplateResult; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -19,6 +20,7 @@ */ final class TTemplateParam extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; use HasIntersectionTrait; /** diff --git a/src/Psalm/Type/Atomic/TTemplatePropertiesOf.php b/src/Psalm/Type/Atomic/TTemplatePropertiesOf.php index 4efe92a602a..48cd32f857d 100644 --- a/src/Psalm/Type/Atomic/TTemplatePropertiesOf.php +++ b/src/Psalm/Type/Atomic/TTemplatePropertiesOf.php @@ -7,6 +7,7 @@ use Psalm\Codebase; use Psalm\Internal\Type\TemplateInferredTypeReplacer; use Psalm\Internal\Type\TemplateResult; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -17,6 +18,7 @@ */ final class TTemplatePropertiesOf extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; /** * @param TPropertiesOf::VISIBILITY_*|null $visibility_filter */ diff --git a/src/Psalm/Type/Atomic/TTemplateValueOf.php b/src/Psalm/Type/Atomic/TTemplateValueOf.php index 583d079578b..23d33af5de0 100644 --- a/src/Psalm/Type/Atomic/TTemplateValueOf.php +++ b/src/Psalm/Type/Atomic/TTemplateValueOf.php @@ -7,6 +7,7 @@ use Psalm\Codebase; use Psalm\Internal\Type\TemplateInferredTypeReplacer; use Psalm\Internal\Type\TemplateResult; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -17,6 +18,7 @@ */ final class TTemplateValueOf extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function __construct( public string $param_name, public string $defining_class, diff --git a/src/Psalm/Type/Atomic/TTypeAlias.php b/src/Psalm/Type/Atomic/TTypeAlias.php index ebda8e4118b..9a76d80405e 100644 --- a/src/Psalm/Type/Atomic/TTypeAlias.php +++ b/src/Psalm/Type/Atomic/TTypeAlias.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -11,6 +12,7 @@ */ final class TTypeAlias extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function __construct( public string $declaring_fq_classlike_name, public string $alias_name, diff --git a/src/Psalm/Type/Atomic/TValueOf.php b/src/Psalm/Type/Atomic/TValueOf.php index 38e09570959..55a9d8d6ab0 100644 --- a/src/Psalm/Type/Atomic/TValueOf.php +++ b/src/Psalm/Type/Atomic/TValueOf.php @@ -6,6 +6,7 @@ use Psalm\Codebase; use Psalm\Storage\EnumCaseStorage; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; use Psalm\Type\Union; @@ -20,6 +21,7 @@ */ final class TValueOf extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function __construct(public Union $type, bool $from_docblock = false) { parent::__construct($from_docblock); diff --git a/src/Psalm/Type/Atomic/TVoid.php b/src/Psalm/Type/Atomic/TVoid.php index cac95d62293..d1cd2faf60c 100644 --- a/src/Psalm/Type/Atomic/TVoid.php +++ b/src/Psalm/Type/Atomic/TVoid.php @@ -4,6 +4,7 @@ namespace Psalm\Type\Atomic; +use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait; use Psalm\Type\Atomic; /** @@ -13,6 +14,7 @@ */ final class TVoid extends Atomic { + use UnserializeMemoryUsageSuppressionTrait; public function getKey(bool $include_extra = true): string { return 'void'; From 823c9180fd801bf8bee948afb57a8b9673f38af0 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 17 Jan 2024 13:32:15 +0100 Subject: [PATCH 58/63] Fixup --- src/Psalm/Internal/PhpTraverser/CustomTraverser.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Internal/PhpTraverser/CustomTraverser.php b/src/Psalm/Internal/PhpTraverser/CustomTraverser.php index 397601d4e59..f1e2673572d 100644 --- a/src/Psalm/Internal/PhpTraverser/CustomTraverser.php +++ b/src/Psalm/Internal/PhpTraverser/CustomTraverser.php @@ -29,7 +29,7 @@ public function __construct() * @param Node $node node to traverse * @return Node Result of traversal (may be original node or new one) */ - protected function traverseNode(Node $node): void + protected function traverseNode(Node $node): Node { foreach ($node->getSubNodeNames() as $name) { $subNode = &$node->$name; @@ -60,7 +60,7 @@ protected function traverseNode(Node $node): void } if ($traverseChildren) { - $this->traverseNode($subNode); + $subNode = $this->traverseNode($subNode); if ($this->stopTraversal) { break; } @@ -88,6 +88,8 @@ protected function traverseNode(Node $node): void } } } + + return $node; } /** From 950293c6e74c6e9db842f537c5722755b1594313 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 17 Jan 2024 13:37:23 +0100 Subject: [PATCH 59/63] Fixup test --- tests/ReportOutputTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ReportOutputTest.php b/tests/ReportOutputTest.php index 0f0461987c1..b30aa993e9d 100644 --- a/tests/ReportOutputTest.php +++ b/tests/ReportOutputTest.php @@ -757,7 +757,7 @@ public function testJsonReport(): void 'other_references' => null, ], [ - 'link' => 'https://psalm.dev/047', + 'link' => 'https://psalm.dev/020', 'severity' => 'error', 'line_from' => 8, 'line_to' => 8, From 2a7d6d2750d5745539f739c403a2309e50c10e87 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 17 Jan 2024 13:45:40 +0100 Subject: [PATCH 60/63] cs-fix --- src/Psalm/Issue/RiskyTruthyFalsyComparison.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Psalm/Issue/RiskyTruthyFalsyComparison.php b/src/Psalm/Issue/RiskyTruthyFalsyComparison.php index 68ab4e1322b..1fe4865beb0 100644 --- a/src/Psalm/Issue/RiskyTruthyFalsyComparison.php +++ b/src/Psalm/Issue/RiskyTruthyFalsyComparison.php @@ -1,5 +1,7 @@ Date: Wed, 17 Jan 2024 13:52:58 +0100 Subject: [PATCH 61/63] Try bumping PHP on windows CI --- .github/workflows/windows-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index 3314de45861..70923db72b8 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -54,7 +54,7 @@ jobs: - name: Set up PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.1' + php-version: '8.3' ini-values: zend.assertions=1, assert.exception=1, opcache.enable_cli=1, opcache.jit=function, opcache.jit_buffer_size=512M tools: composer:v2 coverage: none From 58c5598405580aed08ec86cd82567f2e2e913f85 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 17 Jan 2024 17:01:31 +0100 Subject: [PATCH 62/63] Try disabling opcache --- .github/workflows/windows-ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index 70923db72b8..7fefd1f13f9 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -54,8 +54,9 @@ jobs: - name: Set up PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.3' - ini-values: zend.assertions=1, assert.exception=1, opcache.enable_cli=1, opcache.jit=function, opcache.jit_buffer_size=512M + php-version: '8.1' + #ini-values: zend.assertions=1, assert.exception=1, opcache.enable_cli=1, opcache.jit=function, opcache.jit_buffer_size=512M + ini-values: zend.assertions=1, assert.exception=1 tools: composer:v2 coverage: none extensions: none, curl, dom, filter, intl, json, libxml, mbstring, openssl, opcache, pcre, phar, reflection, simplexml, spl, tokenizer, xml, xmlwriter From 3411dd8eb5b73666a47979893facc2912357809f Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 17 Jan 2024 17:07:48 +0100 Subject: [PATCH 63/63] Skip opcache on windows --- .github/workflows/windows-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index 7fefd1f13f9..c5bd292b267 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -59,7 +59,8 @@ jobs: ini-values: zend.assertions=1, assert.exception=1 tools: composer:v2 coverage: none - extensions: none, curl, dom, filter, intl, json, libxml, mbstring, openssl, opcache, pcre, phar, reflection, simplexml, spl, tokenizer, xml, xmlwriter + #extensions: none, curl, dom, filter, intl, json, libxml, mbstring, openssl, opcache, pcre, phar, reflection, simplexml, spl, tokenizer, xml, xmlwriter + extensions: none, curl, dom, filter, intl, json, libxml, mbstring, openssl, pcre, phar, reflection, simplexml, spl, tokenizer, xml, xmlwriter env: fail-fast: true