private static void ExtractMenuItemsFromAttributes() { s_MenuItemsPerMode = new Dictionary <string, MenuItemsTree <MenuItemScriptCommand> >(); s_MenuItemsDefaultMode = new Dictionary <string, MenuItemScriptCommand>(); var menuItems = TypeCache.GetMethodsWithAttribute <MenuItem>(); // Order the menu items to start with Unity menus before projects menus. That way if there is a duplicate, the project one is flagged as duplicate foreach (var methodInfo in menuItems.OrderBy(m => !Utility.FastStartsWith(m.DeclaringType.Assembly.FullName, "UnityEditor", "unityeditor"))) { if (!ValidateMethodForMenuCommand(methodInfo)) { continue; } foreach (var attribute in methodInfo.GetCustomAttributes(typeof(MenuItem), false)) { string menuName = SanitizeMenuItemName(((MenuItem)attribute).menuItem); string[] editorModes = ((MenuItem)attribute).editorModes; foreach (var editorMode in editorModes) { if (editorMode == k_DefaultModeId) { if (s_MenuItemsDefaultMode.TryGetValue(menuName, out var menuItem)) { menuItem.Update((MenuItem)attribute, methodInfo); } else { s_MenuItemsDefaultMode.Add(menuName, MenuItemScriptCommand.Initialize(menuName, (MenuItem)attribute, methodInfo)); } } else { if (s_MenuItemsPerMode.TryGetValue(editorMode, out var menuItemsPerMode)) { MenuItemScriptCommand menuItem = menuItemsPerMode.FindItem(menuName); if (menuItem == null) { menuItemsPerMode.AddChildSearch(MenuItemScriptCommand.Initialize(menuName, (MenuItem)attribute, methodInfo)); } else { menuItem.Update((MenuItem)attribute, methodInfo); } } else { var newMenusPerMode = new MenuItemsTree <MenuItemScriptCommand>(); newMenusPerMode.AddChildSearch(MenuItemScriptCommand.Initialize(menuName, (MenuItem)attribute, methodInfo)); s_MenuItemsPerMode.Add(editorMode, newMenusPerMode); } } } } } CleanUpInvalidMenuItems(); }