classEvaluationBudget
final class EvaluationBudget
The work one analysis is allowed to do before it gives up and widens.
Following calls and re-walking loop bodies is what makes the analyzer precise, and is also what makes it possible for a pathological input to run forever. The budget bounds both, so an exhausted budget degrades the result into gaps rather than hanging the run.
Constants§
public const READING_ALLOWANCE = 4How many times the search's budget reading what was found may take.
Properties§
public int $maxSteps = 20000public int $maxDepth = 4public int $maxLoopPasses = 2Methods§
public function __construct(
public int $maxSteps = 20000,
public int $maxDepth = 4,
public int $maxLoopPasses = 2,
)Parameters
$maxSteps | int | How many expressions may be evaluated while walking one body |
$maxDepth | int | How many nested calls may be followed |
$maxLoopPasses | int | How many times a loop body is re-walked |
public function spend(): boolSpends one step, reporting whether the budget still allows work.
Returns
boolTest cases 19
CalleeReturnsTest::testReadDoesNotRememberWhatAnExhaustedBudgetCutShortcallsCalleeReturnsTest::testValueOfStopsOnceTheBudgetIsExhaustedcallsCallersTest::testReachesCannotTellOnceTheBudgetIsSpentcallsDeriverTest::testRunKeepsReadingPastTheSearchBudgetOnlyAtDepthZerocallsDeriverTest::testSolveAtExitsDoesNotHandBackWhatItFoundOnceTheBudgetRanOutcallsDeriverTest::testSolveForgetsWhatItFoundOnceTheBudgetRanOutcallsDeriverTest::testSolveUnlessSpentGivesNothingOnceTheBudgetIsSpentcallsDeriverTest::testSpentTellsWhetherTheBudgetIsExhaustedcallsEntryBinderTest::testFromCallersStopsOnceTheBudgetIsSpentcallsEntryBinderTest::testOpenOriginBlamesTheBudgetOnlyOnceItIsSpentcallsEntryBinderTest::testParameterBindingsLeaveAParameterOpenOnceTheBudgetIsSpentcallsPropertyWritesTest::testValuesOfSkipsTheWritersOnceTheBudgetIsSpentcallsSliceExecutorTest::testRunWhenClosingStopsOnceTheReadingBudgetIsSpentcallsEvaluationBudgetTest::testIsExhaustedOnceMoreWasSpentThanAllowedcallsEvaluationBudgetTest::testIsSpentIsClearedByAResetcallsEvaluationBudgetTest::testIsSpentOnlyOnceFourTimesTheStepBudgetWasSpentcallsEvaluationBudgetTest::testResetStartsANewFilecallsEvaluationBudgetTest::testSpendReportsWhenTheBudgetRunsOutcallsEvaluationBudgetTest::testSpentCountsTheStepsTakencalls
Called from 2
public function isExhausted(): boolWhether the step budget is used up.
Returns
boolTest cases 4
Called from 10
- method-call SqlCatalog\Core\Analysis\Derivation\CalleeReturns::valueOf() packages/sql-catalog/src/Core/Analysis/Derivation/CalleeReturns.php:76
- method-call SqlCatalog\Core\Analysis\Derivation\CalleeReturns::read() packages/sql-catalog/src/Core/Analysis/Derivation/CalleeReturns.php:105
- method-call SqlCatalog\Core\Analysis\Derivation\Deriver::solve() packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:114
- method-call SqlCatalog\Core\Analysis\Derivation\Deriver::solveAtExits() packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:146
- method-call SqlCatalog\Core\Analysis\Derivation\Deriver::spent() packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:190
- method-call SqlCatalog\Core\Analysis\Derivation\Deriver::solveUnlessSpent() packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:201
- method-call SqlCatalog\Core\Analysis\Derivation\EntryBinder::parameterBindings() packages/sql-catalog/src/Core/Analysis/Derivation/EntryBinder.php:211
- method-call SqlCatalog\Core\Analysis\Derivation\EntryBinder::fromCallers() packages/sql-catalog/src/Core/Analysis/Derivation/EntryBinder.php:244
- method-call SqlCatalog\Core\Analysis\Derivation\EntryBinder::openOrigin() packages/sql-catalog/src/Core/Analysis/Derivation/EntryBinder.php:314
- method-call SqlCatalog\Core\Analysis\Derivation\SliceExecutor::run() packages/sql-catalog/src/Core/Analysis/Derivation/SliceExecutor.php:112
public function isSpent(): boolWhether even the work of reading what is already in hand has to stop.
Running out of budget stops the search from going anywhere new, but the statement it has found so far is still read, so a search cut short keeps the parts of the statement it did find. Reading has a limit of its own, several times the search's, so a pathological input still ends.
Returns
boolTest cases 2
Called from 2
Calls 1
- class-const EvaluationBudget::READING_ALLOWANCE() line 67
public function spent(): intHow many steps have been spent.
Returns
intTest cases 9
BackwardSlicerTest::testWalkListStopsOnceEveryPathIsDonecallsSliceExecutorTest::testApplyBindsADeclarationcallsSliceExecutorTest::testApplyEntersAClosureWithoutEvaluatingAnythingcallsSliceExecutorTest::testApplyEntersAnArrowFunctioncallsSliceExecutorTest::testApplyGoesOnFromThePassAForeachReachedOverWhatItFirstReadcallsSliceExecutorTest::testApplyLeavesAnyOtherStatementAsItFoundItcallsEvaluationBudgetTest::testIsSpentOnlyOnceFourTimesTheStepBudgetWasSpentcallsEvaluationBudgetTest::testResetStartsANewFilecallsEvaluationBudgetTest::testSpentCountsTheStepsTakencalls
public function reset(): voidRefills the budget, at the beginning of a new body.
Test cases 4
Private surface 1§
Implementation details, listed for orientation only.
private int $stepsTest cases 130§
Test cases that cover or call this symbol, from the coverage report and from the analyzed test sources.
Dedicated tests 8
EvaluationBudgetTest::testIsExhaustedOnceMoreWasSpentThanAllowedcallsEvaluationBudgetTest::testIsSpentIsClearedByAResetcallsEvaluationBudgetTest::testIsSpentOnlyOnceFourTimesTheStepBudgetWasSpentcallsEvaluationBudgetTest::testResetStartsANewFilecallsEvaluationBudgetTest::testSpendReportsWhenTheBudgetRunsOutcallsEvaluationBudgetTest::testSpentCountsTheStepsTakencallsEvaluationBudgetTest::testTheDefaultsBoundStepsDepthAndLoopPassescallsEvaluationBudgetTest::testTheReadingAllowanceIsFourTimesTheSearchcalls
Other tests reaching this symbol 122
CatalogCommandTestcallsCallEvaluatorTest::testFollowStopsAtTheDepthLimitcallsConstantReaderTestcallsCalleeReturnsTest::testCacheableRejectsAllocationsEvenInsideArrayscallsCalleeReturnsTest::testParametersBindsEachArgumentToThePositionItIsPassedIncallsCalleeReturnsTest::testParametersFallsBackToTheDefaultOfAParameterNotPassedcallsCalleeReturnsTest::testParametersLeavesAParameterNeitherPassedNorDefaultedOpencallsCalleeReturnsTest::testParametersLeavesAVariadicParameterOpenWhateverIsPassedcallsCalleeReturnsTest::testReadDoesNotRememberWhatAnExhaustedBudgetCutShortcallsCalleeReturnsTest::testReadEntersTheCalleeSoACallBackIntoItIsNotFollowedAgaincallsCalleeReturnsTest::testReadReturnsNullFromABodyWithoutAReturncallsCalleeReturnsTest::testReadRunsAMethodInItsOwnClassAndAFunctionInTheCallersClasscallsCalleeReturnsTest::testReadUnitesWhatEveryReturnCanReturncallsCalleeReturnsTest::testReturnedReadsNullFromABareReturncallsCalleeReturnsTest::testReturnedReadsWhatTheReturnDependsOnFromTheStartcallsCalleeReturnsTest::testReturnedUnitesEveryRunOfTheSlicecallsCalleeReturnsTest::testReturnsInFindsEveryReturnOfTheBodyInTheOrderWrittencallsCalleeReturnsTest::testReturnsInLeavesOutTheReturnsOfFunctionsAndClassesDeclaredInTheBodycallsCalleeReturnsTest::testValueOfAnswersACallWithTheSameArgumentsFromMemorycallsCalleeReturnsTest::testValueOfKeepsAbsenceDistinctFromUnresolvedReturnscallsCalleeReturnsTest::testValueOfLeavesAFunctionWithoutABodyAsACallItDidNotFollowcallsCalleeReturnsTest::testValueOfLeavesAnAbstractMethodAsACallItDidNotFollowcallsCalleeReturnsTest::testValueOfReadsWhatTheCalleeReturnscallsCalleeReturnsTest::testValueOfStopsAtACallAlreadyBeingFollowedcallsCalleeReturnsTest::testValueOfStopsAtTheDepthLimitAndFollowsJustBelowItcallsCalleeReturnsTest::testValueOfStopsOnceTheBudgetIsExhaustedcallsCallersTest::testReachesCannotTellOnceTheBudgetIsSpentcallsCallersTest::testReachesWorksOutTheReceiverOneCallDeepercallsDeriverTest::testBinderIsTheEntryBinderTheDeriverWasWiredWithcallsDeriverTest::testEvaluatorIsTheEvaluatorTheDeriverWasWiredWithcallsDeriverTest::testRunKeepsReadingPastTheSearchBudgetOnlyAtDepthZerocallsDeriverTest::testSolveAtExitsDoesNotHandBackWhatItFoundOnceTheBudgetRanOutcallsDeriverTest::testSolveForgetsWhatItFoundOnceTheBudgetRanOutcallsDeriverTest::testSolveMarksTheWaysInJoinedForWantOfBudgetAsCombinedcallsDeriverTest::testSolveReadsWhatTheGoalsNeedWithTheNamesItWasGivencallsDeriverTest::testSolveUnlessSpentGivesNothingOnceTheBudgetIsSpentcallsDeriverTest::testSpentTellsWhetherTheBudgetIsExhaustedcallsEntryBinderTest::testBindingsLeaveThePropertiesAloneWithoutAReaderOfPropertyWritescallsEntryBinderTest::testFileScopeBindsTheGlobalsAnExtensionDeclarescallsEntryBinderTest::testFromCallersMarksTheWaysInFoundBeforeTheBudgetRanOutAsCutShortcallsEntryBinderTest::testFromCallersStopsOnceTheBudgetIsSpentcallsEntryBinderTest::testOpenOriginBlamesTheBudgetOnlyOnceItIsSpentcallsEntryBinderTest::testParameterBindingsBlameTheBudgetWhenLookingForCallersSpentItcallsEntryBinderTest::testParameterBindingsLeaveAParameterOpenOnceTheBudgetIsSpentcallsEntryBinderTest::testParameterBindingsStopAtTheDepthLimitcallsCallbackEffectsTest::testApplyFollowsMutationsOfTheCallbackParametercallsCallbackEffectsTest::testApplyLeavesCallbacksWithoutAReceiverOpencallsCallbackEffectsTest::testApplyRunsClosureEffectsThroughCapturedAliasesOfItsReceivercallsCallbackEffectsTest::testBindKeepsOnlyExplicitClosureCapturesAndPassedArgumentscallsCallbackEffectsTest::testSupportedAcceptsExplicitNullAndVoidReturnscallsCallbackEffectsTest::testSupportedRejectsEarlyReturnsAndReplacementQueriescallsPropertyWritesTest::testValuesOfCollectsWhatEveryWriterLeavescallsPropertyWritesTest::testValuesOfSkipsTheWritersOnceTheBudgetIsSpentcallsBackwardSlicerTest::testAllDoneIsTrueOnlyWhenNoPathNeedsAnythingcallsBackwardSlicerTest::testArriveNamesTheNamedBodyAClosureIsWrittenIncallsBackwardSlicerTest::testBeforeAStatementNotInAnyListArrivesWhereItIscallsBackwardSlicerTest::testBeforeWalksBackOverTheStatementsAheadOfOnecallsBackwardSlicerTest::testBoundMergesRepeatsAndGathersPathsBeyondTheLimitcallsBackwardSlicerTest::testBranchHoldsSeveralRunsAsOneStepcallsBackwardSlicerTest::testLeaveCarriesAFinallyBlockOverItsTryBlockcallsBackwardSlicerTest::testLeaveCarriesPathsOutOfTheirOwnercallsBackwardSlicerTest::testLeaveClosureTakesOnlyTheUseListFromOutsidecallsBackwardSlicerTest::testOutsideIsWhatAClosureTakesFromWhereItIsWrittencallsBackwardSlicerTest::testOverStopsAPathOnceTheBudgetIsSpentcallsBackwardSlicerTest::testOverWalksDeclarationsBlocksLoopsAndConditionAssignmentscallsBackwardSlicerTest::testOwningStatementIsTheStatementAnArmBelongsTocallsBackwardSlicerTest::testSliceFromAnArrowFunctionTakesWhatItCapturesFromWhereItIsWrittencallsBackwardSlicerTest::testSliceFromANodeOutsideAnyStatementArrivesAtNothingcallsBackwardSlicerTest::testSliceFromEndWalksBackFromTheEndOfABodycallsBackwardSlicerTest::testSliceFromKeepsWhatTheCallDependsOnInTheOrderItRunscallsBackwardSlicerTest::testWalkArmsWalksEachArmFromItsEndcallsBackwardSlicerTest::testWalkListStopsOnceEveryPathIsDonecallsLoopPassesTest::testBindingIsAStepOnlyForAPathThatNeedsTheLoopsVariablescallsLoopPassesTest::testBodyOfIsWhatALoopRepeatscallsLoopPassesTest::testBoundSaysWhetherAPathTookOneOfTheLoopsPassescallsLoopPassesTest::testContinuesSaysWhetherAnotherPassCouldChangeWhatIsNeededcallsLoopPassesTest::testEnteringReadsWhatALoopGoesOverBeforeItsFirstPasscallsLoopPassesTest::testExpressionsWalkBackOverAListLastFirstcallsLoopPassesTest::testIsLoopRecognisesEveryKindOfLoopcallsLoopPassesTest::testLeaveBodyFollowsAPointInsideALoopBackThroughEarlierPassescallsLoopPassesTest::testPassWalksBackOverOneWholePasscallsLoopPassesTest::testRunsListTheStatementAfterEachNumberOfPassesUpToTheLimitcallsLoopPassesTest::testRunsOfADoWhileAlwaysIncludeAPasscallsLoopPassesTest::testRunsStopOnceAPassCannotChangeWhatIsNeededcallsLoopPassesTest::testRunsTakeExactlyAsManyPassesAsAWrittenOutArrayHasElementscallsLoopPassesTest::testWrittenPassesCountsOnlyAnArrayWrittenOutInFullcallsSliceExecutorTest::testAffordableRunsIsWhatTheBudgetPaysForAlongTheStepscallsSliceExecutorTest::testApplyBindsADeclarationcallsSliceExecutorTest::testApplyEntersAClosureWithoutEvaluatingAnythingcallsSliceExecutorTest::testApplyEntersAnArrowFunctioncallsSliceExecutorTest::testApplyGoesOnFromThePassAForeachReachedOverWhatItFirstReadcallsSliceExecutorTest::testApplyLeavesAnyOtherStatementAsItFoundItcallsSliceExecutorTest::testAssignOnceTheBudgetIsSpentcallsSliceExecutorTest::testRunAbandonsTheStepsLeftOnceTheSearchBudgetIsExhaustedcallsSliceExecutorTest::testRunSizesTheLimitFromTheBudgetWhenNoneIsGivencallsSliceExecutorTest::testRunWhenClosingReadsOnPastTheSearchBudgetcallsSliceExecutorTest::testRunWhenClosingStopsOnceTheReadingBudgetIsSpentcallsExpressionEvaluatorTest::testEvaluateGivesUpOnceTheBudgetIsSpentcallsRegistryTestcallsInterpreterTest::testAnalyzeGivesEveryCallTheWholeBudgetcallsInterpreterTest::testAnalyzeSpendsNoMoreThanTheBudgetItIsGivencallsInterpreterTest::testAnalyzeWithATinyBudgetStillReportsTheCallcallsModelQueriesTestcallsReferenceEvaluatorTestcallsCallContextTestcallsModelContextTest::testKeepsTheModelContractInputscallsQueryModelInterfaceTestcallsBuilderCallsTestcallsBuilderQueriesTestcallsCallbackModelTest::testApplyRunsSourceDeclaredLocalScopescallsCallbackModelTest::testCheckedPreservesAVisibleGapWhenTheCallbackExceedsItsBudgetcallsCallbackModelTest::testClosedRejectsWidenedResultsAndForeignIdentitiescallsCallbackModelTest::testConditionalKeepsBothOutcomesOfWhenAndUnlesscallsCallbackModelTest::testNestedRestoresOuterClausesAndGroupsOnlyNewPredicatescallsCallModelTestcallsLaravelExtensionTest::testModelsRegistersLaravelSemanticsThroughTheOptionalContractcallsAnalysisOptionsTest::testBudgetIsTheOneThatWasGivencallsAnalysisOptionsTest::testWithExtensionsKeepsTheBudgetcallsAnalyzerTest::testACallSiteSurvivesTheWalkNotReachingItcallsAnalyzerTest::testAHelperReturnCutShortByTheLoopBudgetCannotCloseTheCallercallsJsonReporterTestcallsTextReporterTestcalls
Relations§
Instantiated in 3
- new SqlCatalog\Core\Analysis\Derivation\SliceExecutor::__construct() packages/sql-catalog/src/Core/Analysis/Derivation/SliceExecutor.php:80
- new SqlCatalog\Core\Analysis\Interpreter::__construct() packages/sql-catalog/src/Core/Analysis/Interpreter.php:95
- new SqlCatalog\Facade\AnalysisOptions::budget() packages/sql-catalog/src/Facade/AnalysisOptions.php:46
Method calls 16
- method-call SqlCatalog\Core\Analysis\Derivation\CalleeReturns::valueOf() packages/sql-catalog/src/Core/Analysis/Derivation/CalleeReturns.php:76
- method-call SqlCatalog\Core\Analysis\Derivation\CalleeReturns::read() packages/sql-catalog/src/Core/Analysis/Derivation/CalleeReturns.php:105
- method-call SqlCatalog\Core\Analysis\Derivation\Deriver::solve() packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:114
- method-call SqlCatalog\Core\Analysis\Derivation\Deriver::solveAtExits() packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:146
- method-call SqlCatalog\Core\Analysis\Derivation\Deriver::spent() packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:190
- method-call SqlCatalog\Core\Analysis\Derivation\Deriver::solveUnlessSpent() packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:201
- method-call SqlCatalog\Core\Analysis\Derivation\EntryBinder::parameterBindings() packages/sql-catalog/src/Core/Analysis/Derivation/EntryBinder.php:211
- method-call SqlCatalog\Core\Analysis\Derivation\EntryBinder::fromCallers() packages/sql-catalog/src/Core/Analysis/Derivation/EntryBinder.php:244
- method-call SqlCatalog\Core\Analysis\Derivation\EntryBinder::openOrigin() packages/sql-catalog/src/Core/Analysis/Derivation/EntryBinder.php:314
- method-call SqlCatalog\Core\Analysis\Derivation\Slice\BackwardSlicer::over() packages/sql-catalog/src/Core/Analysis/Derivation/Slice/BackwardSlicer.php:279
- method-call SqlCatalog\Core\Analysis\Derivation\SliceExecutor::run() packages/sql-catalog/src/Core/Analysis/Derivation/SliceExecutor.php:112
- method-call SqlCatalog\Core\Analysis\Derivation\SliceExecutor::run() packages/sql-catalog/src/Core/Analysis/Derivation/SliceExecutor.php:112
- method-call SqlCatalog\Core\Analysis\ExpressionEvaluator::evaluate() packages/sql-catalog/src/Core/Analysis/ExpressionEvaluator.php:63
- method-call SqlCatalog\Core\Analysis\ExpressionEvaluator::evaluate() packages/sql-catalog/src/Core/Analysis/ExpressionEvaluator.php:64
- method-call SqlCatalog\Core\Analysis\Interpreter::analyze() packages/sql-catalog/src/Core/Analysis/Interpreter.php:116
- method-call SqlCatalog\Core\Analysis\Interpreter::visit() packages/sql-catalog/src/Core/Analysis/Interpreter.php:217
Type declarations 18
- type SqlCatalog\Core\Analysis\Derivation\CalleeReturns packages/sql-catalog/src/Core/Analysis/Derivation/CalleeReturns.php:39
- type SqlCatalog\Core\Analysis\Derivation\CalleeReturns packages/sql-catalog/src/Core/Analysis/Derivation/CalleeReturns.php:49
- type SqlCatalog\Core\Analysis\Derivation\Deriver packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:52
- type SqlCatalog\Core\Analysis\Derivation\Deriver packages/sql-catalog/src/Core/Analysis/Derivation/Deriver.php:72
- type SqlCatalog\Core\Analysis\Derivation\EntryBinder packages/sql-catalog/src/Core/Analysis/Derivation/EntryBinder.php:43
- type SqlCatalog\Core\Analysis\Derivation\EntryBinder packages/sql-catalog/src/Core/Analysis/Derivation/EntryBinder.php:57
- type SqlCatalog\Core\Analysis\Derivation\Slice\BackwardSlicer packages/sql-catalog/src/Core/Analysis/Derivation/Slice/BackwardSlicer.php:39
- type SqlCatalog\Core\Analysis\Derivation\Slice\BackwardSlicer packages/sql-catalog/src/Core/Analysis/Derivation/Slice/BackwardSlicer.php:56
- type SqlCatalog\Core\Analysis\Derivation\Slice\LoopPasses packages/sql-catalog/src/Core/Analysis/Derivation/Slice/LoopPasses.php:36
- type SqlCatalog\Core\Analysis\Derivation\Slice\LoopPasses packages/sql-catalog/src/Core/Analysis/Derivation/Slice/LoopPasses.php:47
- type SqlCatalog\Core\Analysis\Derivation\SliceExecutor packages/sql-catalog/src/Core/Analysis/Derivation/SliceExecutor.php:64
- type SqlCatalog\Core\Analysis\Derivation\SliceExecutor packages/sql-catalog/src/Core/Analysis/Derivation/SliceExecutor.php:74
- type SqlCatalog\Core\Analysis\ExpressionEvaluator packages/sql-catalog/src/Core/Analysis/ExpressionEvaluator.php:29
- type SqlCatalog\Core\Analysis\ExpressionEvaluator packages/sql-catalog/src/Core/Analysis/ExpressionEvaluator.php:41
- type SqlCatalog\Core\Analysis\Interpreter packages/sql-catalog/src/Core/Analysis/Interpreter.php:65
- type SqlCatalog\Core\Analysis\Interpreter packages/sql-catalog/src/Core/Analysis/Interpreter.php:86
- type SqlCatalog\Facade\AnalysisOptions packages/sql-catalog/src/Facade/AnalysisOptions.php:26
- type SqlCatalog\Facade\AnalysisOptions packages/sql-catalog/src/Facade/AnalysisOptions.php:44