From 1df819236d5920771712bfe25cc44111392499c9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 24 Nov 2025 02:54:59 +0100 Subject: [PATCH 01/12] source mapper: added support for columns --- src/Tracy/BlueScreen/assets/section-stack-callStack.phtml | 2 +- src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml | 2 +- src/Tracy/Debugger/Debugger.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml b/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml index 74b3744d8..f11007713 100644 --- a/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml +++ b/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml @@ -57,7 +57,7 @@ if (!$stack) {
- +
diff --git a/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml b/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml index 492a5269d..bde95a747 100644 --- a/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml +++ b/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml @@ -33,7 +33,7 @@ $sourceMapped = $sourceOriginal ? Debugger::mapSource($file, $line) : null;

File:

- +
diff --git a/src/Tracy/Debugger/Debugger.php b/src/Tracy/Debugger/Debugger.php index 23b3c2f26..e4ff1eebf 100644 --- a/src/Tracy/Debugger/Debugger.php +++ b/src/Tracy/Debugger/Debugger.php @@ -586,7 +586,7 @@ public static function addSourceMapper(callable $mapper): void } - /** @return array{file: string, line: int, label: string, active: bool} */ + /** @return array{file: string, line: int, column: int, label: string, active: bool} */ public static function mapSource(string $file, int $line): ?array { foreach (self::$sourceMappers as $mapper) { From 60bbab29f76f8d8a7b11a07ec608cbf38a964823 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 24 Nov 2025 03:13:40 +0100 Subject: [PATCH 02/12] open in editor: added support for columns --- src/Tracy/BlueScreen/BlueScreen.php | 2 +- src/Tracy/Helpers.php | 3 ++- tools/open-in-editor/linux/open-editor.sh | 14 +++++++++----- tools/open-in-editor/windows/open-editor.js | 15 ++++++++------- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Tracy/BlueScreen/BlueScreen.php b/src/Tracy/BlueScreen/BlueScreen.php index 4596b7bb7..bd1984e3f 100644 --- a/src/Tracy/BlueScreen/BlueScreen.php +++ b/src/Tracy/BlueScreen/BlueScreen.php @@ -321,7 +321,7 @@ public static function highlightFile( ? CodeHighlighter::highlightPhp($source, $line, $column) : '
' . CodeHighlighter::highlightLine(htmlspecialchars($source, ENT_IGNORE, 'UTF-8'), $line, $column) . '
'; - if ($editor = Helpers::editorUri($file, $line)) { + if ($editor = Helpers::editorUri($file, line: $line, column: $column)) { $source = substr_replace($source, ' title="Ctrl-Click to open in editor" data-tracy-href="' . Helpers::escapeHtml($editor) . '"', 4, 0); } diff --git a/src/Tracy/Helpers.php b/src/Tracy/Helpers.php index 8264fb6f1..0452926df 100644 --- a/src/Tracy/Helpers.php +++ b/src/Tracy/Helpers.php @@ -57,6 +57,7 @@ public static function editorUri( string $action = 'open', string $search = '', string $replace = '', + ?int $column = null, ): ?string { if (Debugger::$editor && $file && ($action === 'create' || @is_file($file))) { // @ - may trigger error @@ -67,7 +68,7 @@ public static function editorUri( return strtr(Debugger::$editor, [ '%action' => $action, '%file' => rawurlencode($file), - '%line' => $line ?: 1, + '%line' => ($line ?: 1) . ($column ? ':' . $column : ''), '%search' => rawurlencode($search), '%replace' => rawurlencode($replace), ]); diff --git a/tools/open-in-editor/linux/open-editor.sh b/tools/open-in-editor/linux/open-editor.sh index 69e37be83..8cabf2789 100755 --- a/tools/open-in-editor/linux/open-editor.sh +++ b/tools/open-in-editor/linux/open-editor.sh @@ -6,7 +6,7 @@ declare -A mapping # # Visual Studio Code -#editor='code --goto "$FILE":"$LINE"' +#editor='code --goto "$FILE":"$LINE":"$COLUMN"' # Emacs #editor='emacs +$LINE "$FILE"' # gVim @@ -17,11 +17,9 @@ declare -A mapping #editor='pluma +$LINE "$FILE"' # PHPStorm # To enable PHPStorm command-line interface, folow this guide: https://www.jetbrains.com/help/phpstorm/working-with-the-ide-features-from-command-line.html -#editor='phpstorm --line $LINE "$FILE"' +#editor='phpstorm --line $LINE --column $COLUMN "$FILE"' # VS Codium #editor='codium --goto "$FILE":"$LINE"' -# Visual Studio Code -#editor='code --goto "$FILE":"$LINE"' # # Optionally configure custom mapping here: @@ -56,16 +54,21 @@ action=`echo $url | sed -r "s/$regex/\1/i"` uri_params=`echo $url | sed -r "s/$regex/\2/i"` file=`get_param $uri_params "file"` -line=`get_param $uri_params "line"` +line_param=`get_param $uri_params "line"` search=`get_param $uri_params "search"` replace=`get_param $uri_params "replace"` +# Parse line and column from line parameter (format: "12:5" or just "12") +IFS=':' read -r line column <<< "$line_param" +column="${column:-1}" + # Debug? #echo "action '$action'" #echo "file '$file'" #echo "line '$line'" #echo "search '$search'" #echo "replace '$replace'" +#echo "column '$column'" # Convert URI encoded codes to normal characters (e.g. '%2F' => '/'). printf -v file "${file//%/\\x}" @@ -102,6 +105,7 @@ fi # Format the command according to the selected editor. command="${editor//\$FILE/$file}" command="${command//\$LINE/$line}" +command="${command//\$COLUMN/$column}" # Debug? #echo $command diff --git a/tools/open-in-editor/windows/open-editor.js b/tools/open-in-editor/windows/open-editor.js index ac1093e70..86f699483 100644 --- a/tools/open-in-editor/windows/open-editor.js +++ b/tools/open-in-editor/windows/open-editor.js @@ -1,7 +1,7 @@ var settings = { // PhpStorm - // editor: '"C:\\Program Files\\JetBrains\\PhpStorm 2018.1.2\\bin\\phpstorm64.exe" --line %line% "%file%"', + // editor: '"C:\\Program Files\\JetBrains\\PhpStorm 2018.1.2\\bin\\phpstorm64.exe" --line %line% --column %column% "%file%"', // title: 'PhpStorm', // NetBeans @@ -14,7 +14,7 @@ var settings = { // editor: '"C:\\Program Files\\SciTE\\scite.exe" "-open:%file%" -goto:%line%', // EmEditor - // editor: '"C:\\Program Files\\EmEditor\\EmEditor.exe" "%file%" /l %line%', + // editor: '"C:\\Program Files\\EmEditor\\EmEditor.exe" "%file%" /l %line% /cl %column%', // PSPad Editor // editor: '"C:\\Program Files\\PSPad editor\\PSPad.exe" -%line% "%file%"', @@ -26,7 +26,7 @@ var settings = { // editor: '"C:\\Program Files\\Sublime Text 2\\sublime_text.exe" "%file%:%line%"', // Visual Studio Code / VSCodium - // editor: '"C:\\Program Files\\Microsoft VS Code\\Code.exe" --goto "%file%:%line%"', + // editor: '"C:\\Program Files\\Microsoft VS Code\\Code.exe" --goto "%file%:%line%:%column%"', mappings: { // '/remotepath': '/localpath' @@ -41,7 +41,7 @@ if (!settings.editor) { } var url = WScript.Arguments(0); -var match = /^editor:\/\/(open|create|fix)\/?\?file=([^&]+)&line=(\d+)(?:&search=([^&]*)&replace=([^&]*))?/.exec(url); +var match = /^editor:\/\/(open|create|fix)\/?\?file=([^&]+)&line=(\d+)(?::(\d+))?(?:&search=([^&]*)&replace=([^&]*))?/.exec(url); if (!match) { WScript.Echo('Unexpected URI ' + url); WScript.Quit(); @@ -53,8 +53,9 @@ for (var i in match) { var action = match[1]; var file = match[2]; var line = match[3]; -var search = match[4]; -var replace = match[5]; +var column = match[4] || 1; +var search = match[5]; +var replace = match[6]; var shell = new ActiveXObject('WScript.Shell'); var fileSystem = new ActiveXObject('Scripting.FileSystemObject'); @@ -76,7 +77,7 @@ if (action === 'create' && !fileSystem.FileExists(file)) { fileSystem.OpenTextFile(file, 2).Write(lines.join('\n')); } -var command = settings.editor.replace(/%line%/, line).replace(/%file%/, file); +var command = settings.editor.replace(/%line%/, line).replace(/%column%/, column).replace(/%file%/, file); shell.Exec(command); if (settings.title) { From 0a39429598e41324f45fcc166c4145adf3776abd Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 31 Oct 2025 15:20:00 +0100 Subject: [PATCH 03/12] examples: added enum dump example --- examples/dump.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/dump.php b/examples/dump.php index fc007ea74..0037d1365 100644 --- a/examples/dump.php +++ b/examples/dump.php @@ -35,6 +35,14 @@ echo "

Objects

\n"; echo "

Hover over the name \$baz to see property declaring class and over the hash #5 to see same objects.

\n"; +enum Suit +{ + case Clubs; + case Diamonds; + case Hearts; + case Spades; +} + class ParentClass { public $foo = [10, 20]; @@ -42,6 +50,8 @@ class ParentClass protected $bar = 30; private $baz = 'parent'; + + public Suit $enum = Suit::Clubs; } #[\AllowDynamicProperties] @@ -87,7 +97,8 @@ class ChildClass extends ParentClass $arr = [ fopen(__FILE__, 'r'), - new class {}, + new class { +}, function ($x, $y) use (&$arr, $obj) {}, ]; From 53a04c56bc8a65c5cef461414567a8699f93f8f0 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 31 Oct 2025 03:16:00 +0100 Subject: [PATCH 04/12] moved Dumper tests --- tests/{Tracy => Dumper}/Dumper.debugInfo.phpt | 0 tests/{Tracy => Dumper}/Dumper.dump().cli.phpt | 0 tests/{Tracy => Dumper}/Dumper.dump().html.phpt | 0 tests/{Tracy => Dumper}/Dumper.dump().text.phpt | 0 tests/{Tracy => Dumper}/Dumper.exposeObject.phpt | 0 tests/{Tracy => Dumper}/Dumper.keys.phpt | 0 tests/{Tracy => Dumper}/Dumper.keysToHide.phpt | 0 tests/{Tracy => Dumper}/Dumper.nesting-error.phpt | 0 tests/{Tracy => Dumper}/Dumper.objectExporters.phpt | 0 tests/{Tracy => Dumper}/Dumper.references74.phpt | 0 tests/{Tracy => Dumper}/Dumper.scrubber.phpt | 0 tests/{Tracy => Dumper}/Dumper.sensitiveValue.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().collapse.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().depth.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().key.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().lazy.auto.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().lazy.no.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().lazy.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().live.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().locale.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().location.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().recursion.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().references.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().see.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().snapshot.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().specialChars.phpt | 0 tests/{Tracy => Dumper}/Dumper.toHtml().specials.phpt | 0 tests/{Tracy => Dumper}/Dumper.toTerminal().phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().depth.phpt | 0 .../{Tracy => Dumper}/Dumper.toText().enumProperty.PhpToken.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().enumProperty.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().locale.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().location.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().nohash.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().recursion.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().references.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().see.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().specialChars.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().specials.dom.php84.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().specials.dom.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().specials.ds.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().specials.enum.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().specials.fiber.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().specials.generator.phpt | 0 tests/{Tracy => Dumper}/Dumper.toText().specials.phpt | 0 tests/{Tracy => Dumper}/dump().cli.phpt | 0 tests/{Tracy => Dumper}/dump().html.phpt | 0 tests/{Tracy => Dumper}/dump().text.phpt | 0 tests/{Tracy => Dumper}/fixtures/DumpClass.php | 0 51 files changed, 0 insertions(+), 0 deletions(-) rename tests/{Tracy => Dumper}/Dumper.debugInfo.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.dump().cli.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.dump().html.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.dump().text.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.exposeObject.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.keys.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.keysToHide.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.nesting-error.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.objectExporters.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.references74.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.scrubber.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.sensitiveValue.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().collapse.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().depth.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().key.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().lazy.auto.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().lazy.no.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().lazy.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().live.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().locale.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().location.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().recursion.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().references.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().see.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().snapshot.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().specialChars.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toHtml().specials.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toTerminal().phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().depth.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().enumProperty.PhpToken.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().enumProperty.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().locale.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().location.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().nohash.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().recursion.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().references.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().see.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().specialChars.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().specials.dom.php84.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().specials.dom.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().specials.ds.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().specials.enum.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().specials.fiber.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().specials.generator.phpt (100%) rename tests/{Tracy => Dumper}/Dumper.toText().specials.phpt (100%) rename tests/{Tracy => Dumper}/dump().cli.phpt (100%) rename tests/{Tracy => Dumper}/dump().html.phpt (100%) rename tests/{Tracy => Dumper}/dump().text.phpt (100%) rename tests/{Tracy => Dumper}/fixtures/DumpClass.php (100%) diff --git a/tests/Tracy/Dumper.debugInfo.phpt b/tests/Dumper/Dumper.debugInfo.phpt similarity index 100% rename from tests/Tracy/Dumper.debugInfo.phpt rename to tests/Dumper/Dumper.debugInfo.phpt diff --git a/tests/Tracy/Dumper.dump().cli.phpt b/tests/Dumper/Dumper.dump().cli.phpt similarity index 100% rename from tests/Tracy/Dumper.dump().cli.phpt rename to tests/Dumper/Dumper.dump().cli.phpt diff --git a/tests/Tracy/Dumper.dump().html.phpt b/tests/Dumper/Dumper.dump().html.phpt similarity index 100% rename from tests/Tracy/Dumper.dump().html.phpt rename to tests/Dumper/Dumper.dump().html.phpt diff --git a/tests/Tracy/Dumper.dump().text.phpt b/tests/Dumper/Dumper.dump().text.phpt similarity index 100% rename from tests/Tracy/Dumper.dump().text.phpt rename to tests/Dumper/Dumper.dump().text.phpt diff --git a/tests/Tracy/Dumper.exposeObject.phpt b/tests/Dumper/Dumper.exposeObject.phpt similarity index 100% rename from tests/Tracy/Dumper.exposeObject.phpt rename to tests/Dumper/Dumper.exposeObject.phpt diff --git a/tests/Tracy/Dumper.keys.phpt b/tests/Dumper/Dumper.keys.phpt similarity index 100% rename from tests/Tracy/Dumper.keys.phpt rename to tests/Dumper/Dumper.keys.phpt diff --git a/tests/Tracy/Dumper.keysToHide.phpt b/tests/Dumper/Dumper.keysToHide.phpt similarity index 100% rename from tests/Tracy/Dumper.keysToHide.phpt rename to tests/Dumper/Dumper.keysToHide.phpt diff --git a/tests/Tracy/Dumper.nesting-error.phpt b/tests/Dumper/Dumper.nesting-error.phpt similarity index 100% rename from tests/Tracy/Dumper.nesting-error.phpt rename to tests/Dumper/Dumper.nesting-error.phpt diff --git a/tests/Tracy/Dumper.objectExporters.phpt b/tests/Dumper/Dumper.objectExporters.phpt similarity index 100% rename from tests/Tracy/Dumper.objectExporters.phpt rename to tests/Dumper/Dumper.objectExporters.phpt diff --git a/tests/Tracy/Dumper.references74.phpt b/tests/Dumper/Dumper.references74.phpt similarity index 100% rename from tests/Tracy/Dumper.references74.phpt rename to tests/Dumper/Dumper.references74.phpt diff --git a/tests/Tracy/Dumper.scrubber.phpt b/tests/Dumper/Dumper.scrubber.phpt similarity index 100% rename from tests/Tracy/Dumper.scrubber.phpt rename to tests/Dumper/Dumper.scrubber.phpt diff --git a/tests/Tracy/Dumper.sensitiveValue.phpt b/tests/Dumper/Dumper.sensitiveValue.phpt similarity index 100% rename from tests/Tracy/Dumper.sensitiveValue.phpt rename to tests/Dumper/Dumper.sensitiveValue.phpt diff --git a/tests/Tracy/Dumper.toHtml().collapse.phpt b/tests/Dumper/Dumper.toHtml().collapse.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().collapse.phpt rename to tests/Dumper/Dumper.toHtml().collapse.phpt diff --git a/tests/Tracy/Dumper.toHtml().depth.phpt b/tests/Dumper/Dumper.toHtml().depth.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().depth.phpt rename to tests/Dumper/Dumper.toHtml().depth.phpt diff --git a/tests/Tracy/Dumper.toHtml().key.phpt b/tests/Dumper/Dumper.toHtml().key.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().key.phpt rename to tests/Dumper/Dumper.toHtml().key.phpt diff --git a/tests/Tracy/Dumper.toHtml().lazy.auto.phpt b/tests/Dumper/Dumper.toHtml().lazy.auto.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().lazy.auto.phpt rename to tests/Dumper/Dumper.toHtml().lazy.auto.phpt diff --git a/tests/Tracy/Dumper.toHtml().lazy.no.phpt b/tests/Dumper/Dumper.toHtml().lazy.no.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().lazy.no.phpt rename to tests/Dumper/Dumper.toHtml().lazy.no.phpt diff --git a/tests/Tracy/Dumper.toHtml().lazy.phpt b/tests/Dumper/Dumper.toHtml().lazy.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().lazy.phpt rename to tests/Dumper/Dumper.toHtml().lazy.phpt diff --git a/tests/Tracy/Dumper.toHtml().live.phpt b/tests/Dumper/Dumper.toHtml().live.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().live.phpt rename to tests/Dumper/Dumper.toHtml().live.phpt diff --git a/tests/Tracy/Dumper.toHtml().locale.phpt b/tests/Dumper/Dumper.toHtml().locale.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().locale.phpt rename to tests/Dumper/Dumper.toHtml().locale.phpt diff --git a/tests/Tracy/Dumper.toHtml().location.phpt b/tests/Dumper/Dumper.toHtml().location.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().location.phpt rename to tests/Dumper/Dumper.toHtml().location.phpt diff --git a/tests/Tracy/Dumper.toHtml().phpt b/tests/Dumper/Dumper.toHtml().phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().phpt rename to tests/Dumper/Dumper.toHtml().phpt diff --git a/tests/Tracy/Dumper.toHtml().recursion.phpt b/tests/Dumper/Dumper.toHtml().recursion.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().recursion.phpt rename to tests/Dumper/Dumper.toHtml().recursion.phpt diff --git a/tests/Tracy/Dumper.toHtml().references.phpt b/tests/Dumper/Dumper.toHtml().references.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().references.phpt rename to tests/Dumper/Dumper.toHtml().references.phpt diff --git a/tests/Tracy/Dumper.toHtml().see.phpt b/tests/Dumper/Dumper.toHtml().see.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().see.phpt rename to tests/Dumper/Dumper.toHtml().see.phpt diff --git a/tests/Tracy/Dumper.toHtml().snapshot.phpt b/tests/Dumper/Dumper.toHtml().snapshot.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().snapshot.phpt rename to tests/Dumper/Dumper.toHtml().snapshot.phpt diff --git a/tests/Tracy/Dumper.toHtml().specialChars.phpt b/tests/Dumper/Dumper.toHtml().specialChars.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().specialChars.phpt rename to tests/Dumper/Dumper.toHtml().specialChars.phpt diff --git a/tests/Tracy/Dumper.toHtml().specials.phpt b/tests/Dumper/Dumper.toHtml().specials.phpt similarity index 100% rename from tests/Tracy/Dumper.toHtml().specials.phpt rename to tests/Dumper/Dumper.toHtml().specials.phpt diff --git a/tests/Tracy/Dumper.toTerminal().phpt b/tests/Dumper/Dumper.toTerminal().phpt similarity index 100% rename from tests/Tracy/Dumper.toTerminal().phpt rename to tests/Dumper/Dumper.toTerminal().phpt diff --git a/tests/Tracy/Dumper.toText().depth.phpt b/tests/Dumper/Dumper.toText().depth.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().depth.phpt rename to tests/Dumper/Dumper.toText().depth.phpt diff --git a/tests/Tracy/Dumper.toText().enumProperty.PhpToken.phpt b/tests/Dumper/Dumper.toText().enumProperty.PhpToken.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().enumProperty.PhpToken.phpt rename to tests/Dumper/Dumper.toText().enumProperty.PhpToken.phpt diff --git a/tests/Tracy/Dumper.toText().enumProperty.phpt b/tests/Dumper/Dumper.toText().enumProperty.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().enumProperty.phpt rename to tests/Dumper/Dumper.toText().enumProperty.phpt diff --git a/tests/Tracy/Dumper.toText().locale.phpt b/tests/Dumper/Dumper.toText().locale.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().locale.phpt rename to tests/Dumper/Dumper.toText().locale.phpt diff --git a/tests/Tracy/Dumper.toText().location.phpt b/tests/Dumper/Dumper.toText().location.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().location.phpt rename to tests/Dumper/Dumper.toText().location.phpt diff --git a/tests/Tracy/Dumper.toText().nohash.phpt b/tests/Dumper/Dumper.toText().nohash.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().nohash.phpt rename to tests/Dumper/Dumper.toText().nohash.phpt diff --git a/tests/Tracy/Dumper.toText().phpt b/tests/Dumper/Dumper.toText().phpt similarity index 100% rename from tests/Tracy/Dumper.toText().phpt rename to tests/Dumper/Dumper.toText().phpt diff --git a/tests/Tracy/Dumper.toText().recursion.phpt b/tests/Dumper/Dumper.toText().recursion.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().recursion.phpt rename to tests/Dumper/Dumper.toText().recursion.phpt diff --git a/tests/Tracy/Dumper.toText().references.phpt b/tests/Dumper/Dumper.toText().references.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().references.phpt rename to tests/Dumper/Dumper.toText().references.phpt diff --git a/tests/Tracy/Dumper.toText().see.phpt b/tests/Dumper/Dumper.toText().see.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().see.phpt rename to tests/Dumper/Dumper.toText().see.phpt diff --git a/tests/Tracy/Dumper.toText().specialChars.phpt b/tests/Dumper/Dumper.toText().specialChars.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().specialChars.phpt rename to tests/Dumper/Dumper.toText().specialChars.phpt diff --git a/tests/Tracy/Dumper.toText().specials.dom.php84.phpt b/tests/Dumper/Dumper.toText().specials.dom.php84.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().specials.dom.php84.phpt rename to tests/Dumper/Dumper.toText().specials.dom.php84.phpt diff --git a/tests/Tracy/Dumper.toText().specials.dom.phpt b/tests/Dumper/Dumper.toText().specials.dom.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().specials.dom.phpt rename to tests/Dumper/Dumper.toText().specials.dom.phpt diff --git a/tests/Tracy/Dumper.toText().specials.ds.phpt b/tests/Dumper/Dumper.toText().specials.ds.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().specials.ds.phpt rename to tests/Dumper/Dumper.toText().specials.ds.phpt diff --git a/tests/Tracy/Dumper.toText().specials.enum.phpt b/tests/Dumper/Dumper.toText().specials.enum.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().specials.enum.phpt rename to tests/Dumper/Dumper.toText().specials.enum.phpt diff --git a/tests/Tracy/Dumper.toText().specials.fiber.phpt b/tests/Dumper/Dumper.toText().specials.fiber.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().specials.fiber.phpt rename to tests/Dumper/Dumper.toText().specials.fiber.phpt diff --git a/tests/Tracy/Dumper.toText().specials.generator.phpt b/tests/Dumper/Dumper.toText().specials.generator.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().specials.generator.phpt rename to tests/Dumper/Dumper.toText().specials.generator.phpt diff --git a/tests/Tracy/Dumper.toText().specials.phpt b/tests/Dumper/Dumper.toText().specials.phpt similarity index 100% rename from tests/Tracy/Dumper.toText().specials.phpt rename to tests/Dumper/Dumper.toText().specials.phpt diff --git a/tests/Tracy/dump().cli.phpt b/tests/Dumper/dump().cli.phpt similarity index 100% rename from tests/Tracy/dump().cli.phpt rename to tests/Dumper/dump().cli.phpt diff --git a/tests/Tracy/dump().html.phpt b/tests/Dumper/dump().html.phpt similarity index 100% rename from tests/Tracy/dump().html.phpt rename to tests/Dumper/dump().html.phpt diff --git a/tests/Tracy/dump().text.phpt b/tests/Dumper/dump().text.phpt similarity index 100% rename from tests/Tracy/dump().text.phpt rename to tests/Dumper/dump().text.phpt diff --git a/tests/Tracy/fixtures/DumpClass.php b/tests/Dumper/fixtures/DumpClass.php similarity index 100% rename from tests/Tracy/fixtures/DumpClass.php rename to tests/Dumper/fixtures/DumpClass.php From b9d4107cc762a5f19d101d3a8ebd8bc5a9b9d3a4 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 25 Nov 2024 12:17:42 +0100 Subject: [PATCH 05/12] Dumper: added support for uninitialized lazy objects --- src/Tracy/Dumper/Exposer.php | 24 ++++++++ .../Dumper.toHtml().specials.lazyObject.phpt | 56 +++++++++++++++++++ .../Dumper.toText().specials.lazyObject.phpt | 54 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tests/Dumper/Dumper.toHtml().specials.lazyObject.phpt create mode 100644 tests/Dumper/Dumper.toText().specials.lazyObject.phpt diff --git a/src/Tracy/Dumper/Exposer.php b/src/Tracy/Dumper/Exposer.php index 773f54124..02f2745bb 100644 --- a/src/Tracy/Dumper/Exposer.php +++ b/src/Tracy/Dumper/Exposer.php @@ -21,6 +21,11 @@ final class Exposer { public static function exposeObject(object $obj, Value $value, Describer $describer): void { + if (PHP_VERSION_ID >= 80400 && (new \ReflectionClass($obj))->isUninitializedLazyObject($obj)) { + self::exposeLazyObject($obj, $describer, $value); + return; + } + $values = get_mangled_object_vars($obj); $props = self::getProperties($obj::class); @@ -276,4 +281,23 @@ public static function exposeDsMap( $describer->addPropertyTo($value, (string) $i++, new Ds\Pair($k, $v)); } } + + + private static function exposeLazyObject(object $obj, Describer $describer, Value $value): void + { + $rc = new \ReflectionClass($obj); + foreach ($rc->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { + if (!$prop->isLazy($obj)) { + $describer->addPropertyTo( + $value, + $prop->getName(), + $prop->getValue($obj), + Value::PropertyPublic, + described: $describer->describeEnumProperty($obj::class, $prop->getName(), $prop->getValue($obj)), + ); + } + } + + $value->value .= ' (lazy)'; + } } diff --git a/tests/Dumper/Dumper.toHtml().specials.lazyObject.phpt b/tests/Dumper/Dumper.toHtml().specials.lazyObject.phpt new file mode 100644 index 000000000..02dd62578 --- /dev/null +++ b/tests/Dumper/Dumper.toHtml().specials.lazyObject.phpt @@ -0,0 +1,56 @@ +newLazyGhost(function () {}); + +// new ghost +Assert::match( + <<<'XX' +
LazyClass (lazy) #%d%
+ XX, + Dumper::toHtml($ghost, [Dumper::DEPTH => 3]), +); + +// preinitialized property +$rc->getProperty('id')->setRawValueWithoutLazyInitialization($ghost, 123); + +Assert::match( + <<<'XX' +
LazyClass (lazy) #%d%
+		
id: 123 +
+ XX, + Dumper::toHtml($ghost, [Dumper::DEPTH => 3]), +); + +// proxy +$proxy = $rc->newLazyProxy(function () { return new LazyClass; }); +Assert::match( + <<<'XX' +
LazyClass (lazy) #%d%
+ XX, + Dumper::toHtml($proxy, [Dumper::DEPTH => 3]), +); diff --git a/tests/Dumper/Dumper.toText().specials.lazyObject.phpt b/tests/Dumper/Dumper.toText().specials.lazyObject.phpt new file mode 100644 index 000000000..db52dfab8 --- /dev/null +++ b/tests/Dumper/Dumper.toText().specials.lazyObject.phpt @@ -0,0 +1,54 @@ +newLazyGhost(function () {}); + +// new ghost +Assert::match( + <<<'XX' + LazyClass (lazy) #%d% + XX, + Dumper::toText($ghost, [Dumper::DEPTH => 3]), +); + +// preinitialized property +$rc->getProperty('id')->setRawValueWithoutLazyInitialization($ghost, 123); + +Assert::match( + <<<'XX' + LazyClass (lazy) #%d% + id: 123 + XX, + Dumper::toText($ghost, [Dumper::DEPTH => 3]), +); + +// proxy +$proxy = $rc->newLazyProxy(function () { return new LazyClass; }); +Assert::match( + <<<'XX' + LazyClass (lazy) #%d% + XX, + Dumper::toText($proxy, [Dumper::DEPTH => 3]), +); From ca44b1d4d0fa8eb3db00607bb9396dc40aaa485a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 10 Dec 2021 05:33:06 +0100 Subject: [PATCH 06/12] opened 3.0-dev --- composer.json | 2 +- src/Tracy/Debugger/Debugger.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 00df1da0a..9e04b3a90 100644 --- a/composer.json +++ b/composer.json @@ -46,7 +46,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.11-dev" + "dev-master": "3.0-dev" } } } diff --git a/src/Tracy/Debugger/Debugger.php b/src/Tracy/Debugger/Debugger.php index e4ff1eebf..3280b8d9b 100644 --- a/src/Tracy/Debugger/Debugger.php +++ b/src/Tracy/Debugger/Debugger.php @@ -19,7 +19,7 @@ */ class Debugger { - public const Version = '2.11.0'; + public const Version = '3.0-dev'; /** server modes for Debugger::enable() */ public const From 108fa9401610740db460934e7da043f5ddcdca1f Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 5 Dec 2022 01:21:34 +0100 Subject: [PATCH 07/12] uses PascalCase constants --- src/Bridges/Nette/TracyExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bridges/Nette/TracyExtension.php b/src/Bridges/Nette/TracyExtension.php index d4244cc16..e1ba09527 100644 --- a/src/Bridges/Nette/TracyExtension.php +++ b/src/Bridges/Nette/TracyExtension.php @@ -131,7 +131,7 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class): void if ($this->debugMode) { foreach ($this->config->bar as $item) { if (is_string($item) && substr($item, 0, 1) === '@') { - $item = new Statement(['@' . $builder::THIS_CONTAINER, 'getService'], [substr($item, 1)]); + $item = new Statement(['@' . $builder::ThisContainer, 'getService'], [substr($item, 1)]); } elseif (is_string($item)) { $item = new Statement($item); } From 0e63dac0451a7442d7333b4412a0d251b158d598 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 3 Feb 2022 17:37:54 +0100 Subject: [PATCH 08/12] Logger: added typehints --- src/Tracy/Logger/Logger.php | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/src/Tracy/Logger/Logger.php b/src/Tracy/Logger/Logger.php index 43fd3d201..8b9b14a17 100644 --- a/src/Tracy/Logger/Logger.php +++ b/src/Tracy/Logger/Logger.php @@ -18,23 +18,22 @@ */ class Logger implements ILogger { - /** @var string|null name of the directory where errors should be logged */ - public $directory; + /** name of the directory where errors should be logged */ + public ?string $directory = null; - /** @var string|array|null email or emails to which send error notifications */ - public $email; + /** email or emails to which send error notifications */ + public string|array|null $email = null; - /** @var string|null sender of email notifications */ - public $fromEmail; + /** sender of email notifications */ + public ?string $fromEmail = null; - /** @var mixed interval for sending email is 2 days */ - public $emailSnooze = '2 days'; + /** interval for sending email is 2 days */ + public mixed $emailSnooze = '2 days'; /** @var callable handler for sending emails */ public $mailer; - /** @var BlueScreen|null */ - private $blueScreen; + private ?BlueScreen $blueScreen = null; public function __construct(?string $directory, string|array|null $email = null, ?BlueScreen $blueScreen = null) @@ -81,10 +80,7 @@ public function log(mixed $message, string $level = self::INFO) } - /** - * @param mixed $message - */ - public static function formatMessage($message): string + public static function formatMessage(mixed $message): string { if ($message instanceof \Throwable) { foreach (Helpers::getExceptionChain($message) as $exception) { @@ -104,10 +100,7 @@ public static function formatMessage($message): string } - /** - * @param mixed $message - */ - public static function formatLogLine($message, ?string $exceptionFile = null): string + public static function formatLogLine(mixed $message, ?string $exceptionFile = null): string { return implode(' ', [ date('[Y-m-d H-i-s]'), @@ -155,10 +148,7 @@ protected function logException(\Throwable $exception, ?string $file = null): st } - /** - * @param mixed $message - */ - protected function sendEmail($message): void + protected function sendEmail(mixed $message): void { $snooze = is_numeric($this->emailSnooze) ? $this->emailSnooze @@ -177,10 +167,9 @@ protected function sendEmail($message): void /** * Default mailer. - * @param mixed $message * @internal */ - public function defaultMailer($message, string $email): void + public function defaultMailer(mixed $message, string $email): void { $host = preg_replace('#[^\w.-]+#', '', $_SERVER['SERVER_NAME'] ?? php_uname('n')); mail( From 15639450b5b63eb0fb44155446358f919ea86c0b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 3 Apr 2024 20:38:58 +0200 Subject: [PATCH 09/12] error.log changed to warning.log --- src/Tracy/Debugger/ProductionStrategy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tracy/Debugger/ProductionStrategy.php b/src/Tracy/Debugger/ProductionStrategy.php index 64fbd02c3..a47db9ed7 100644 --- a/src/Tracy/Debugger/ProductionStrategy.php +++ b/src/Tracy/Debugger/ProductionStrategy.php @@ -65,7 +65,7 @@ public function handleError( $err = 'PHP ' . Helpers::errorTypeToString($severity) . ': ' . Helpers::improveError($message) . " in $file:$line"; } - Debugger::tryLog($err, Debugger::ERROR); + Debugger::tryLog($err, Debugger::WARNING); } From 7543389d84c55e73b4fd2c4c9412da3aaeda3b18 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 23 Nov 2024 17:55:20 +0100 Subject: [PATCH 10/12] used attribute Deprecated --- src/Tracy/Debugger/Debugger.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Tracy/Debugger/Debugger.php b/src/Tracy/Debugger/Debugger.php index 3280b8d9b..501e2a17f 100644 --- a/src/Tracy/Debugger/Debugger.php +++ b/src/Tracy/Debugger/Debugger.php @@ -29,19 +29,19 @@ class Debugger public const CookieSecret = 'tracy-debug'; - /** @deprecated use Debugger::Version */ + #[\Deprecated('use Debugger::Version')] public const VERSION = self::Version; - /** @deprecated use Debugger::Development */ + #[\Deprecated('use Debugger::Development')] public const DEVELOPMENT = self::Development; - /** @deprecated use Debugger::Production */ + #[\Deprecated('use Debugger::Production')] public const PRODUCTION = self::Production; - /** @deprecated use Debugger::Detect */ + #[\Deprecated('use Debugger::Detect')] public const DETECT = self::Detect; - /** @deprecated use Debugger::CookieSecret */ + #[\Deprecated('use Debugger::CookieSecret')] public const COOKIE_SECRET = self::CookieSecret; /** in production mode is suppressed any debugging output */ From c427620dbdbbc14ce4f2e5ff64c102e6ffb4fe71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Mon, 22 Dec 2025 22:58:39 +0100 Subject: [PATCH 11/12] Set `tracy.keysToHide` config for Debugger and DIC panel as well, not just for BlueScreen Close #608 --- src/Bridges/Nette/TracyExtension.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Bridges/Nette/TracyExtension.php b/src/Bridges/Nette/TracyExtension.php index e1ba09527..b1141531a 100644 --- a/src/Bridges/Nette/TracyExtension.php +++ b/src/Bridges/Nette/TracyExtension.php @@ -105,12 +105,17 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class): void foreach ($options as $key => $value) { if ($value !== null) { $tbl = [ - 'keysToHide' => 'array_push(Tracy\Debugger::getBlueScreen()->keysToHide, ... ?)', - 'fromEmail' => 'if ($logger instanceof Tracy\Logger) $logger->fromEmail = ?', - 'emailSnooze' => 'if ($logger instanceof Tracy\Logger) $logger->emailSnooze = ?', + 'keysToHide' => [ + '$keysToHide = ?', + 'array_push(Tracy\Debugger::$keysToHide, ...$keysToHide)', + 'array_push(Tracy\Debugger::getBlueScreen()->keysToHide, ...$keysToHide)', + 'array_push(Nette\Bridges\DITracy\ContainerPanel::$keysToHide, ...$keysToHide)', + ], + 'fromEmail' => ['if ($logger instanceof Tracy\Logger) $logger->fromEmail = ?'], + 'emailSnooze' => ['if ($logger instanceof Tracy\Logger) $logger->emailSnooze = ?'], ]; $initialize->addBody($builder->formatPhp( - ($tbl[$key] ?? 'Tracy\Debugger::$' . $key . ' = ?') . ';', + (isset($tbl[$key]) ? implode(";\n", $tbl[$key]) : ('Tracy\Debugger::$' . $key . ' = ?')) . ';', Nette\DI\Helpers::filterArguments([$value]), )); } From 75ed1fedb730643f5c00253af97126612686b1c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Mon, 22 Dec 2025 23:00:36 +0100 Subject: [PATCH 12/12] Use keysToHide when calling `bdump`/`barDump` as well Close #608 --- src/Tracy/Debugger/Debugger.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tracy/Debugger/Debugger.php b/src/Tracy/Debugger/Debugger.php index 501e2a17f..68e680924 100644 --- a/src/Tracy/Debugger/Debugger.php +++ b/src/Tracy/Debugger/Debugger.php @@ -552,6 +552,7 @@ public static function barDump(mixed $var, ?string $title = null, array $options Dumper::TRUNCATE => self::$maxLength, Dumper::LOCATION => self::$showLocation ?: Dumper::LOCATION_CLASS | Dumper::LOCATION_SOURCE, Dumper::LAZY => true, + Dumper::KEYS_TO_HIDE => self::$keysToHide, ])]; }