diff --git a/MCPForUnity/Editor/Tools/ManageScript.cs b/MCPForUnity/Editor/Tools/ManageScript.cs index 4f94df606..8f9c64ec8 100644 --- a/MCPForUnity/Editor/Tools/ManageScript.cs +++ b/MCPForUnity/Editor/Tools/ManageScript.cs @@ -2758,6 +2758,14 @@ private static void CheckDuplicateMethodSignatures(string contents, System.Colle string returnType = sm.Groups[1].Value; string methodName = sm.Groups[2].Value; if (string.Equals(returnType, "new", StringComparison.Ordinal)) continue; // constructor invocation, not a method declaration + // A punctuation "return type" means this match is a CALL, not a declaration: + // the opening brace of a method body ("{ Foo();") or an expression-bodied + // member ("=> Foo();"). Both sit at class-member depth, so the brace-depth + // guard below cannot reject them. + if (returnType.Length == 0) continue; + char returnTypeStart = returnType[0]; + if (!char.IsLetter(returnTypeStart) && returnTypeStart != '_' + && returnTypeStart != '@' && returnTypeStart != '(') continue; if (IsCSharpKeyword(methodName)) continue; int paramCount = CountTopLevelParams(sm.Groups[3].Value); string paramTypes = ExtractParamTypes(sm.Groups[3].Value); diff --git a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptValidationTests.cs b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptValidationTests.cs index 0b1aa7d0a..1cc527e8c 100644 --- a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptValidationTests.cs +++ b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptValidationTests.cs @@ -227,6 +227,55 @@ public void Process(string x) { } "Overloads with different param types but same count should not be flagged"); } + [Test] + public void DuplicateDetection_ExplicitInterfaceImplementation_NotFlagged() + { + string code = @"using UnityEngine; +public interface IThing { void Notify(); } +public class Foo : MonoBehaviour, IThing +{ + void IThing.Notify() + { + Ping(); + } + + private void Ping() { } +}"; + var errors = CallValidateScriptSyntaxUnity(code); + Assert.IsFalse(HasDuplicateMethodError(errors), + "A call as the first statement of an explicit interface implementation is not a declaration"); + } + + [Test] + public void DuplicateDetection_ExpressionBodiedCall_NotFlagged() + { + string code = @"using UnityEngine; +public class Foo : MonoBehaviour +{ + public int Total => Count(); + + private int Count() => 0; +}"; + var errors = CallValidateScriptSyntaxUnity(code); + Assert.IsFalse(HasDuplicateMethodError(errors), + "A call inside an expression-bodied member is not a declaration"); + } + + [Test] + public void DuplicateDetection_FieldInitializerCall_NotFlagged() + { + string code = @"using UnityEngine; +public class Foo : MonoBehaviour +{ + private static bool _enabled = ReadPref(); + + private static bool ReadPref() { return false; } +}"; + var errors = CallValidateScriptSyntaxUnity(code); + Assert.IsFalse(HasDuplicateMethodError(errors), + "A call in a field initializer is not a declaration"); + } + // --- Duplicate method detection: true positive tests --- [Test]