changeset 2323:48fd6f717c4f

Fix bug where CompleterServices could be added to unexpected command options Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-May/019040.html Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-June/019063.html
author Andrew Azores <aazores@redhat.com>
date Wed, 01 Jun 2016 11:41:22 -0400
parents 52d7d3d03fa7
children 6521ebfe69cd
files launcher/src/main/java/com/redhat/thermostat/launcher/internal/TabCompletion.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/TabCompletionTest.java
diffstat 2 files changed, 90 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/TabCompletion.java	Tue May 31 12:43:36 2016 -0400
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/TabCompletion.java	Wed Jun 01 11:41:22 2016 -0400
@@ -49,6 +49,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -99,17 +100,20 @@
 
     private void addCompleterServiceImpl(TreeCompleter.Node command, CompleterService service) {
         for (Map.Entry<CliCommandOption, ? extends TabCompleter> entry : service.getOptionCompleters().entrySet()) {
-            if (entry.getKey() == CliCommandOption.POSITIONAL_ARG_COMPLETION) {
+            CliCommandOption cliCommandOption = entry.getKey();
+            if (cliCommandOption == CliCommandOption.POSITIONAL_ARG_COMPLETION) {
                 TreeCompleter.Node node = new TreeCompleter.Node(command.getTag() + " completer", entry.getValue());
                 node.setRestartNode(command);
                 command.addBranch(node);
             }
-            for (TreeCompleter.Node branch : command.getBranches()) {
-                Set<String> completerOptions = getCompleterOptions(entry.getKey());
-                if (completerOptions.contains(branch.getTag())) {
-                    TreeCompleter.Node node = new TreeCompleter.Node(command.getTag() + " completer", entry.getValue());
-                    node.setRestartNode(command);
-                    branch.addBranch(node);
+            if (completerIsApplicable(cliCommandOption, command)) {
+                for (TreeCompleter.Node branch : command.getBranches()) {
+                    if (branch.getTag().equals("-" + cliCommandOption.getOpt())
+                            || branch.getTag().equals("--" + cliCommandOption.getLongOpt())) {
+                        TreeCompleter.Node node = new TreeCompleter.Node(command.getTag() + " completer", entry.getValue());
+                        node.setRestartNode(command);
+                        branch.addBranch(node);
+                    }
                 }
             }
         }
@@ -129,23 +133,30 @@
 
     private void removeCompleterServiceImpl(TreeCompleter.Node command, CompleterService service) {
         for (Map.Entry<CliCommandOption, ? extends TabCompleter> entry : service.getOptionCompleters().entrySet()) {
-            if (entry.getKey() == CliCommandOption.POSITIONAL_ARG_COMPLETION) {
+            CliCommandOption cliCommandOption = entry.getKey();
+            if (cliCommandOption == CliCommandOption.POSITIONAL_ARG_COMPLETION) {
                 command.removeByTag(command.getTag() + " completer");
             }
             for (TreeCompleter.Node branch : command.getBranches()) {
-                Set<String> completerOptions = getCompleterOptions(entry.getKey());
-                if (completerOptions.contains(branch.getTag())) {
+                if (branch.getTag().equals("-" + cliCommandOption.getOpt())
+                        || branch.getTag().equals("--" + cliCommandOption.getLongOpt())) {
                     command.removeByTag(branch.getTag());
                 }
             }
         }
     }
 
-    private static Set<String> getCompleterOptions(CliCommandOption option) {
-        Set<String> options = new HashSet<>();
-        options.add(LONG_OPTION_PREFIX + option.getLongOpt());
-        options.add(SHORT_OPTION_PREFIX + option.getOpt());
-        return options;
+    private static boolean completerIsApplicable(CliCommandOption option, TreeCompleter.Node node) {
+        boolean matchesLongOpt = false;
+        boolean matchesShortOpt = false;
+        for (TreeCompleter.Node branch : node.getBranches()) {
+            if (branch.getTag().equals("--" + option.getLongOpt())) {
+                matchesLongOpt = true;
+            } else if (branch.getTag().equals("-" + option.getOpt())) {
+                matchesShortOpt = true;
+            }
+        }
+        return matchesLongOpt && matchesShortOpt;
     }
 
     public void setupTabCompletion(ConsoleReader reader, CommandInfoSource commandInfoSource, BundleContext context, ClientPreferences prefs) {
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/TabCompletionTest.java	Tue May 31 12:43:36 2016 -0400
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/TabCompletionTest.java	Wed Jun 01 11:41:22 2016 -0400
@@ -52,7 +52,6 @@
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.logging.Logger;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
@@ -68,14 +67,12 @@
 public class TabCompletionTest {
 
     private TabCompletion tabCompletion;
-    private Logger log;
     private TreeCompleter treeCompleter;
     private Map<String, TreeCompleter.Node> commandMap;
 
     @Before
     @SuppressWarnings("unchecked")
     public void setup() {
-        log = mock(Logger.class);
         treeCompleter = mock(TreeCompleter.class);
         commandMap = new HashMap<>();
         tabCompletion = new TabCompletion(treeCompleter, commandMap);
@@ -144,6 +141,70 @@
         }
     }
 
+    @Test
+    public void testAddCompleterWithConflictingShortOpt() {
+        ConsoleReader reader = mock(ConsoleReader.class);
+
+        Options mockOptions = new Options();
+        mockOptions.addOption("a", "agentId", true, "Agent ID");
+
+        Options fakeOptions = new Options();
+        fakeOptions.addOption("a", "all", false, "all data");
+
+        CommandInfo mockCommand = mock(CommandInfo.class);
+        when(mockCommand.getName()).thenReturn("mock-command");
+        when(mockCommand.getBundles()).thenReturn(Collections.<BundleInformation>emptyList());
+        when(mockCommand.getDescription()).thenReturn("description");
+        when(mockCommand.getEnvironments()).thenReturn(EnumSet.of(Environment.CLI, Environment.SHELL));
+        when(mockCommand.getOptions()).thenReturn(mockOptions);
+
+        CommandInfo fakeCommand = mock(CommandInfo.class);
+        when(fakeCommand.getName()).thenReturn("fake-command");
+        when(fakeCommand.getBundles()).thenReturn(Collections.<BundleInformation>emptyList());
+        when(fakeCommand.getDescription()).thenReturn("description");
+        when(fakeCommand.getEnvironments()).thenReturn(EnumSet.of(Environment.CLI, Environment.SHELL));
+        when(fakeCommand.getOptions()).thenReturn(fakeOptions);
+
+        CommandInfoSource infoSource = mock(CommandInfoSource.class);
+        when(infoSource.getCommandInfos()).thenReturn(Arrays.asList(mockCommand, fakeCommand));
+        when(infoSource.getCommandInfo(mockCommand.getName())).thenReturn(mockCommand);
+        when(infoSource.getCommandInfo(fakeCommand.getName())).thenReturn(fakeCommand);
+
+        BundleContext context = mock(BundleContext.class);
+
+        ClientPreferences prefs = mock(ClientPreferences.class);
+
+        CompleterService service = mock(CompleterService.class);
+        when(service.getCommands()).thenReturn(TabCompletion.ALL_COMMANDS_COMPLETER);
+        Map completerMap = new HashMap();
+        TabCompleter completer = mock(TabCompleter.class);
+        completerMap.put(new CliCommandOption("a", "agentId", true, "Agent ID", false), completer);
+        when(service.getOptionCompleters()).thenReturn(completerMap);
+
+        tabCompletion.addCompleterService(service);
+        tabCompletion.setupTabCompletion(reader, infoSource, context, prefs);
+
+        TreeCompleter.Node mockNode = commandMap.get("mock-command");
+        assertThat(mockNode, is(not(equalTo(null))));
+        for (TreeCompleter.Node branch : mockNode.getBranches()) {
+            if (branch.getTag().equals("--agentId")) {
+                assertThat(branch.getBranches(), is(not(equalTo(Collections.<TreeCompleter.Node>emptyList()))));
+            } else if (branch.getTag().equals("-a")) {
+                assertThat(branch.getBranches(), is(not(equalTo(Collections.<TreeCompleter.Node>emptyList()))));
+            }
+        }
+
+        TreeCompleter.Node fakeNode = commandMap.get("fake-command");
+        assertThat(fakeNode, is(not(equalTo(null))));
+        for (TreeCompleter.Node branch : fakeNode.getBranches()) {
+            if (branch.getTag().equals("--all")) {
+                assertThat(branch.getBranches(), is(equalTo(Collections.<TreeCompleter.Node>emptyList())));
+            } else if (branch.getTag().equals("-a")) {
+                assertThat(branch.getBranches(), is(equalTo(Collections.<TreeCompleter.Node>emptyList())));
+            }
+        }
+    }
+
     private void doSetupTabCompletion() {
         ConsoleReader reader = mock(ConsoleReader.class);