Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions MCPForUnity/Editor/Tools/ReadConsole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public static class ReadConsole
private static FieldInfo _messageField;
private static FieldInfo _fileField;
private static FieldInfo _lineField;
private static PropertyInfo _consoleFlagsProperty;
private static MethodInfo _setFilteringTextMethod;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and related symbols first.
git ls-files 'MCPForUnity/Editor/Tools/ReadConsole.cs' 'MCPForUnity/Editor/Tools/*.cs' 'MCPForUnity/Runtime/Helpers/*.cs' | sed 's#^`#FILE` #'

echo
echo "== AST outline for ReadConsole.cs =="
ast-grep outline MCPForUnity/Editor/Tools/ReadConsole.cs --view expanded || true

echo
echo "== Relevant symbol search =="
rg -n "_consoleFlagsProperty|_setFilteringTextMethod|GetFilteringText|SetFilteringText|finally|FilteringText|consoleFlags" MCPForUnity/Editor/Tools/ReadConsole.cs MCPForUnity/Editor/Tools -S || true

Repository: CoplayDev/unity-mcp

Length of output: 12739


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the exact method body around the read path.
nl -ba MCPForUnity/Editor/Tools/ReadConsole.cs | sed -n '1,260p'

Repository: CoplayDev/unity-mcp

Length of output: 197


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether console filter text can be read/restored elsewhere in the codebase.
rg -n "GetFilteringText|SetFilteringText|FilteringText" MCPForUnity -S

Repository: CoplayDev/unity-mcp

Length of output: 927


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# If ReadConsole.cs is large, inspect the relevant middle section only.
wc -l MCPForUnity/Editor/Tools/ReadConsole.cs
nl -ba MCPForUnity/Editor/Tools/ReadConsole.cs | sed -n '260,520p'

Repository: CoplayDev/unity-mcp

Length of output: 241


🏁 Script executed:

#!/bin/bash
set -euo pipefail
nl -ba MCPForUnity/Editor/Tools/ReadConsole.cs | sed -n '1,520p'

Repository: CoplayDev/unity-mcp

Length of output: 197


🌐 Web query:

Unity Editor LogEntries GetFilteringText SetFilteringText API

💡 Result:

The GetFilteringText and SetFilteringText methods are internal API methods belonging to the UnityEditor.LogEntries class [1][2]. Because these methods are internal and not part of the public Unity Scripting API, they are not intended for use in production code and their signatures or functionality can change without warning [1][3]. These methods are primarily used by Unity's own Editor code—specifically the Console Window—to manage the text filter string currently applied to the console's log entries [2][4]. Key characteristics include: - Purpose: They control the search filter string used to narrow down which log entries are displayed in the Unity Editor Console [2]. - Access: As internal methods, they cannot be accessed directly via standard code references. Developers who require this functionality often use C# reflection to access the UnityEditor.LogEntries class at runtime [5][6]. - Usage in Unity's Source: The Unity ConsoleWindow class invokes GetFilteringText to retrieve the current filter state and SetFilteringText to update the filter when a user types into the Console's search field [2]. Because they are not documented public APIs, using them via reflection is considered an unstable practice for Unity development [7][5]. Developers looking to interact with the Console should be aware that these internal calls may fail if Unity changes its internal architecture in future versions [8].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path("MCPForUnity/Editor/Tools/ReadConsole.cs")
lines = p.read_text().splitlines()
for start, end in [(250, 450)]:
    for i in range(start, min(end, len(lines)) + 1):
        print(f"{i:4d}: {lines[i-1]}")
PY

Repository: CoplayDev/unity-mcp

Length of output: 10298


Keep the Console mutations in cleanup.

SetFilteringText("") runs before the try, so a throw there skips restoring consoleFlags; when it succeeds, the search text also stays cleared. Save/restore the filter text when GetFilteringText is available, and move both mutations under the same finally.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@MCPForUnity/Editor/Tools/ReadConsole.cs` at line 34, The console state
mutations in ReadConsole should be scoped together so cleanup always restores
the original state. In the ReadConsole flow, capture the current filtering text
via GetFilteringText before calling SetFilteringText(""), then move both the
filter-text change and the consoleFlags change into the same try/finally path so
any throw still restores both values. Use the existing helper members around
_setFilteringTextMethod, _getFilteringTextMethod, and the console flag fields to
locate and update the affected logic.


// Static constructor for reflection setup
static ReadConsole()
Expand Down Expand Up @@ -99,6 +101,17 @@ static ReadConsole()
if (_lineField == null)
throw new Exception("Failed to reflect LogEntry.line");

// Reflect consoleFlags property to save/restore severity toggles
_consoleFlagsProperty = logEntriesType.GetProperty(
"consoleFlags",
staticFlags
);
// Reflect SetFilteringText to clear/restore the console search filter
_setFilteringTextMethod = logEntriesType.GetMethod(
"SetFilteringText",
staticFlags
);

// (Calibration removed)

}
Expand Down Expand Up @@ -133,6 +146,7 @@ public static object HandleCommand(JObject @params)
|| _messageField == null
|| _fileField == null
|| _lineField == null
|| _consoleFlagsProperty == null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the file structure first, then inspect the relevant region.
ast-grep outline MCPForUnity/Editor/Tools/ReadConsole.cs --view expanded || true

echo
echo "---- relevant lines ----"
sed -n '120,190p' MCPForUnity/Editor/Tools/ReadConsole.cs

Repository: CoplayDev/unity-mcp

Length of output: 5025


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '190,330p' MCPForUnity/Editor/Tools/ReadConsole.cs

Repository: CoplayDev/unity-mcp

Length of output: 6822


Don’t gate clear on consoleFlags. HandleCommand rejects every action when _consoleFlagsProperty is missing, but clear only needs _clearMethod. Move that guard into the get path so clear still works on Unity versions without consoleFlags.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@MCPForUnity/Editor/Tools/ReadConsole.cs` at line 149, HandleCommand is
rejecting all commands when _consoleFlagsProperty is null, but clear only
depends on _clearMethod. Update the guard logic in ReadConsole.HandleCommand so
the consoleFlagsProperty check is only applied for the get path, and keep clear
available whenever _clearMethod exists, even on Unity versions without
consoleFlags.

)
{
// Log the error here as well for easier debugging in Unity Console
Expand Down Expand Up @@ -246,6 +260,25 @@ bool includeStacktrace
int resolvedCursor = Mathf.Max(0, cursor ?? 0);
int pageEndExclusive = resolvedCursor + resolvedPageSize;

// Save and override console severity toggles so that StartGettingEntries
// returns all entries regardless of the Console window's UI filter state.
// Unity's internal LogEntries.StartGettingEntries() respects these flags
// and silently returns 0 when a toggle is off.
int savedConsoleFlags = (int)_consoleFlagsProperty.GetValue(null);
int forcedFlags = savedConsoleFlags
| (1 << 7) // LogLevelLog
| (1 << 8) // LogLevelWarning
| (1 << 9); // LogLevelError
_consoleFlagsProperty.SetValue(null, forcedFlags);

// Also clear the console search filter to avoid text-based filtering
// at the source; the tool applies its own filterText parameter later.
// GetFilteringText may not exist, so we clear without saving.
if (_setFilteringTextMethod != null)
{
_setFilteringTextMethod.Invoke(null, new object[] { string.Empty });
}

try
{
// LogEntries requires calling Start/Stop around GetEntries/GetEntryInternal.
Expand Down Expand Up @@ -392,6 +425,15 @@ bool includeStacktrace
McpLog.Error($"[ReadConsole] Failed to call EndGettingEntries: {e}");
// Don't return error here as we might have valid data, but log it.
}
// Restore the original console severity toggles
try
{
_consoleFlagsProperty.SetValue(null, savedConsoleFlags);
}
catch (Exception e)
{
McpLog.Error($"[ReadConsole] Failed to restore console flags: {e}");
}
}

if (usePaging)
Expand Down