Skip to content

fix(build): avoid compile-time VisionOS enum references#1113

Open
JMartinezRuiz wants to merge 2 commits intoCoplayDev:betafrom
JMartinezRuiz:codex/fix-visionos-buildtarget
Open

fix(build): avoid compile-time VisionOS enum references#1113
JMartinezRuiz wants to merge 2 commits intoCoplayDev:betafrom
JMartinezRuiz:codex/fix-visionos-buildtarget

Conversation

@JMartinezRuiz
Copy link
Copy Markdown

@JMartinezRuiz JMartinezRuiz commented May 6, 2026

Description

Follow-up to #1063.

That PR fixed one part of the VisionOS compatibility problem by moving the direct enum references behind UNITY_2023_2_OR_NEWER. New reports in #1112, plus the later comment on #1063, show that this still is not quite safe: some Unity 2023.2.x installations do not expose BuildTarget.VisionOS / BuildTargetGroup.VisionOS, so the package can still fail to compile before Unity MCP is usable.

This changes the mapping to avoid compile-time references to the VisionOS enum values. VisionOS is now resolved by enum name at runtime, only when the current editor actually exposes it.

Changes Made

  • Remove direct BuildTarget.VisionOS and BuildTargetGroup.VisionOS references from BuildTargetMapping.
  • Resolve VisionOS dynamically through Enum.TryParse.
  • Keep normal build target aliases unchanged.
  • Return a specific error when visionos is requested but unavailable in the current Unity installation.
  • Add EditMode tests for known aliases and VisionOS available/unavailable behavior.

Testing/Screenshots/Recordings

  • git diff --check
  • Unity 2022.3.4f1 batchmode compile of TestProjects/UnityMCPTests completed successfully:
    • Tundra build success
    • Exiting batchmode successfully now!

I did not run a real VisionOS build locally because I do not have the VisionOS build module/target installed. The positive path is preserved by resolving the enum by name when Unity exposes it.

Documentation Updates

No tools or resources were added, removed, or modified.

Related Issues

Fixes #1112
Follow-up to #1063

Summary by CodeRabbit

  • New Features

    • Runtime support added for VisionOS build target detection across Unity versions.
  • Improvements

    • Standardized and clarified "unknown build target" messages with more actionable guidance.
  • Tests

    • Added unit tests covering build target resolution, unknown-target handling, and VisionOS availability scenarios.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c0fea341-6e00-4e12-83b3-dca3d98c26ec

📥 Commits

Reviewing files that changed from the base of the PR and between 2ab0b37 and 75c844f.

📒 Files selected for processing (2)
  • MCPForUnity/Editor/Tools/Build/BuildTargetMapping.cs
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/BuildTargetMappingTests.cs

📝 Walkthrough

Walkthrough

Removes compile-time guards for VisionOS in BuildTargetMapping and adds runtime parsing/helpers; centralizes unknown-target error messages in ManageBuild to use BuildTargetMapping.GetUnknownBuildTargetMessage; adds unit tests validating target resolution and VisionOS-aware errors.

Changes

Build target mapping & messaging

Layer / File(s) Summary
Data Shape / Constants
MCPForUnity/Editor/Tools/Build/BuildTargetMapping.cs
Adds VisionOSName constant and new helpers: `IsVisionOSTarget(string
Core Resolution Logic
MCPForUnity/Editor/Tools/Build/BuildTargetMapping.cs
Removes UNITY_2023_2_OR_NEWER conditional paths; default TryResolveBuildTarget and GetTargetGroup now use runtime enum parsing and VisionOS-aware branches. TryResolveNamedBuildTarget returns a specialized message when VisionOS target exists but its BuildTargetGroup is not exposed.
Message Surface / Wiring
MCPForUnity/Editor/Tools/ManageBuild.cs
Replaces three hardcoded "Unknown target" strings with BuildTargetMapping.GetUnknownBuildTargetMessage(targetName) in HandleBuild, HandlePlatform, and HandleBatch.
Tests / Assets
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/BuildTargetMappingTests.cs, .../BuildTargetMappingTests.cs.meta
Adds NUnit tests covering alias resolution, numeric input rejection, unknown-target messages (including conditional expectations for VisionOS presence), and the Unity .meta asset file.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

safe-to-test

Suggested reviewers

  • dsarno
  • msanatan

Poem

🐰
I hopped through enums, names, and guards,
Tossed compile-time fences into yards,
Now VisionOS is sensed at play,
Messages tidy up the way,
Tests cheer — the mapping hops today!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly describes the primary change: avoiding compile-time VisionOS enum references through runtime resolution.
Description check ✅ Passed The PR description is comprehensive and follows the template structure with all key sections completed: description, changes made, testing, documentation, and related issues.
Linked Issues check ✅ Passed The PR addresses issue #1112 by removing compile-time VisionOS references and resolving them dynamically at runtime, preventing CS0117 compile errors on Unity installations without VisionOS enums.
Out of Scope Changes check ✅ Passed All changes are directly related to resolving the VisionOS enum reference issue: BuildTargetMapping refactoring, ManageBuild.cs message consolidation, and new unit tests. No unrelated or out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/BuildTargetMappingTests.cs (1)

46-53: 💤 Low value

Happy-path branch silently passes without explicit assertion.

When both BuildTarget.VisionOS and BuildTargetGroup.VisionOS are available, error is null and the inner StringAssert.Contains is skipped, so the test only verifies that TryResolveBuildTarget("visionos", out _) returned true — it never asserts that TryResolveNamedBuildTarget itself returned null. Adding an explicit Assert.IsNull(error) (or asserting either null or contains "VisionOS") makes the success path observable.

♻️ Suggested tightening
             if (visionOSAvailable)
             {
                 Assert.IsTrue(BuildTargetMapping.TryResolveBuildTarget("visionos", out _));
-                if (error != null)
-                {
-                    StringAssert.Contains("VisionOS", error);
-                }
+                // Either fully supported (no error) or BuildTargetGroup missing (helpful error).
+                if (error != null)
+                    StringAssert.Contains("VisionOS", error);
+                else
+                    Assert.Pass("VisionOS BuildTarget and BuildTargetGroup both exposed.");
             }
🤖 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
`@TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/BuildTargetMappingTests.cs`
around lines 46 - 53, The test's visionOS success branch only asserts
TryResolveBuildTarget("visionos", out _) is true but doesn't assert that the
returned error from TryResolveNamedBuildTarget is null, so add an explicit
assertion to make the happy path observable: when visionOSAvailable is true,
after Assert.IsTrue(BuildTargetMapping.TryResolveBuildTarget("visionos", out
_)), add Assert.IsNull(error) (or Assert.IsTrue(error == null ||
StringAssert.Contains("VisionOS", error)) if you prefer) to validate
TryResolveNamedBuildTarget's result; locate this change around the
visionOSAvailable block and the variables error and
BuildTargetMapping.TryResolveBuildTarget/TryResolveNamedBuildTarget.
MCPForUnity/Editor/Tools/Build/BuildTargetMapping.cs (1)

30-34: 💤 Low value

Enum.TryParse fallback also accepts numeric strings and deprecated enum names.

Beyond enabling VisionOS resolution, this generalized fallback now resolves any string that matches a BuildTarget enum name case-insensitively, including obsolete targets (e.g. StandaloneOSXIntel, Stadia, Lumin) and any numeric string (e.g. "5", "12") since Enum.TryParse accepts numeric values for the underlying integer. If the intent is solely VisionOS forward-compat, scoping the fallback would avoid accidentally accepting unsupported names; otherwise an Enum.IsDefined check is sufficient to reject pure numeric inputs.

♻️ Targeted alternative
                 default:
-                    if (Enum.TryParse(name, true, out target))
-                        return true;
+                    // Reject pure-numeric inputs that Enum.TryParse would otherwise accept.
+                    if (!int.TryParse(name, out _) &&
+                        Enum.TryParse(name, true, out target) &&
+                        Enum.IsDefined(typeof(BuildTarget), target))
+                    {
+                        return true;
+                    }
                     target = default;
                     return false;

Or, if only VisionOS dynamic resolution is desired:

                 default:
-                    if (Enum.TryParse(name, true, out target))
-                        return true;
+                    if (string.Equals(name, "visionos", StringComparison.OrdinalIgnoreCase) &&
+                        Enum.TryParse(VisionOSName, true, out target))
+                    {
+                        return true;
+                    }
                     target = default;
                     return false;
🤖 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/Build/BuildTargetMapping.cs` around lines 30 - 34,
The current default branch uses Enum.TryParse(name, true, out target) which will
accept numeric strings and obsolete enum names; change the fallback to parse
then validate—call Enum.TryParse(name, true, out target) and then only accept it
if Enum.IsDefined(typeof(BuildTarget), target) (or first reject numeric inputs
via int.TryParse(name, out _) before parsing), or limit acceptance to the
specific VisionOS names you want; update the default branch around the
Enum.TryParse/target handling so it sets target = default and returns false
unless the parsed value passes Enum.IsDefined (or matches the allowed VisionOS
identifiers).
🤖 Prompt for all review comments with 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.

Nitpick comments:
In `@MCPForUnity/Editor/Tools/Build/BuildTargetMapping.cs`:
- Around line 30-34: The current default branch uses Enum.TryParse(name, true,
out target) which will accept numeric strings and obsolete enum names; change
the fallback to parse then validate—call Enum.TryParse(name, true, out target)
and then only accept it if Enum.IsDefined(typeof(BuildTarget), target) (or first
reject numeric inputs via int.TryParse(name, out _) before parsing), or limit
acceptance to the specific VisionOS names you want; update the default branch
around the Enum.TryParse/target handling so it sets target = default and returns
false unless the parsed value passes Enum.IsDefined (or matches the allowed
VisionOS identifiers).

In
`@TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/BuildTargetMappingTests.cs`:
- Around line 46-53: The test's visionOS success branch only asserts
TryResolveBuildTarget("visionos", out _) is true but doesn't assert that the
returned error from TryResolveNamedBuildTarget is null, so add an explicit
assertion to make the happy path observable: when visionOSAvailable is true,
after Assert.IsTrue(BuildTargetMapping.TryResolveBuildTarget("visionos", out
_)), add Assert.IsNull(error) (or Assert.IsTrue(error == null ||
StringAssert.Contains("VisionOS", error)) if you prefer) to validate
TryResolveNamedBuildTarget's result; locate this change around the
visionOSAvailable block and the variables error and
BuildTargetMapping.TryResolveBuildTarget/TryResolveNamedBuildTarget.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6b922606-e138-4cd5-8c2d-37f3a0f1312a

📥 Commits

Reviewing files that changed from the base of the PR and between a2a5edf and 2ab0b37.

📒 Files selected for processing (4)
  • MCPForUnity/Editor/Tools/Build/BuildTargetMapping.cs
  • MCPForUnity/Editor/Tools/ManageBuild.cs
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/BuildTargetMappingTests.cs
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/BuildTargetMappingTests.cs.meta

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

issues: does not contain a definition for 'VisionOS'

1 participant