diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/MenuData.java b/Ghidra/Framework/Docking/src/main/java/docking/action/MenuData.java index 2e4450a464..ed80b7ad0b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/MenuData.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/MenuData.java @@ -15,6 +15,8 @@ */ package docking.action; +import java.util.Arrays; + import javax.swing.Icon; import docking.DockingUtils; @@ -158,6 +160,9 @@ public class MenuData { } public void setMenuPath(String[] newPath) { + if (newPath == null || newPath.length == 0) { + throw new IllegalArgumentException("Menu path cannot be null or empty"); + } MenuData oldData = cloneData(); menuPath = processMenuPath(newPath); int newMnemonic = getMnemonic(newPath); @@ -204,20 +209,15 @@ public class MenuData { } private static String[] processMenuPath(String[] menuPath) { - if (menuPath != null && menuPath.length > 0) { - menuPath[menuPath.length - 1] = processMenuItemName(menuPath[menuPath.length - 1]); + String[] copy = Arrays.copyOf(menuPath, menuPath.length); + if (copy != null && copy.length > 0) { + copy[copy.length - 1] = processMenuItemName(copy[copy.length - 1]); } - return menuPath; + return copy; } private static String processMenuItemName(String string) { - int indexOf = string.indexOf('&'); - if (indexOf >= 0 && indexOf < string.length() - 1) { - return string.substring(0, indexOf) + string.substring(indexOf + 1); - - } - return string; - + return string.replaceFirst("&", ""); } public String getMenuItemName() { diff --git a/Ghidra/Framework/Docking/src/test/java/docking/action/MenuDataTest.java b/Ghidra/Framework/Docking/src/test/java/docking/action/MenuDataTest.java new file mode 100644 index 0000000000..5cc98e9151 --- /dev/null +++ b/Ghidra/Framework/Docking/src/test/java/docking/action/MenuDataTest.java @@ -0,0 +1,64 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.action; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Tests to protect the MenuData class intended behavior + */ +public class MenuDataTest { + + /** + * Mnemonic should be 'T', parsed out of the location of the ampersand in + * 3rd argument in the menuPath. + * The mnemonic is not explicitly set. + */ + @Test + public void testMenuDataParsesMnemonicFromAmpersand() { + MenuData menuData = new MenuData(new String[] { "One", "Two", "&Three" }); + assertEquals(menuData.getMnemonic(), 'T'); + } + + /** + * Mnemonic should be 'h' based on the value that was explicitly set + */ + @Test + public void testMenuDataPassedMnemonicWins() { + MenuData menuData = new MenuData( + new String[] { "One", "Two", "&Three" }, null, null, 'h', null); + assertEquals(menuData.getMnemonic(), 'h'); + } + + /** + * The setMenuPath method should fail to set an invalid (empty) menuPath + */ + @Test(expected = IllegalArgumentException.class) + public void testBreakMenuPath() { + MenuData menuData = new MenuData(new String[] { "One", "Two", "Three" }); + menuData.setMenuPath(new String[0]); + } + + /** + * The MenuData constructor should fail to accept an invalid (empty) menuPath + */ + @Test(expected = IllegalArgumentException.class) + public void testBreakMenuPath2() { + MenuData menuData = new MenuData(new String[] {}); + } +}