8153759: jshell tool: Smart completion detection is not reliable
authorjlahoda
Tue, 24 Jan 2017 13:29:58 +0100
changeset 43363 a4ed2006a4c5
parent 43282 45b751afd11e
child 43364 469da954ee6b
8153759: jshell tool: Smart completion detection is not reliable Summary: Reverting back to smart completion if any action follows a completion action. Reviewed-by: rfield
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Wed Jul 05 22:44:47 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Tue Jan 24 13:29:58 2017 +0100
@@ -45,6 +45,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -57,6 +58,7 @@
 import jdk.internal.jline.WindowsTerminal;
 import jdk.internal.jline.console.ConsoleReader;
 import jdk.internal.jline.console.KeyMap;
+import jdk.internal.jline.console.Operation;
 import jdk.internal.jline.console.UserInterruptException;
 import jdk.internal.jline.console.completer.Completer;
 import jdk.internal.jline.console.history.History;
@@ -90,7 +92,12 @@
             term = new JShellUnixTerminal(input);
         }
         term.init();
-        in = new ConsoleReader(cmdin, cmdout, term);
+        AtomicBoolean allowSmart = new AtomicBoolean();
+        in = new ConsoleReader(cmdin, cmdout, term) {
+            @Override public KeyMap getKeys() {
+                return new CheckCompletionKeyMap(super.getKeys(), allowSmart);
+            }
+        };
         in.setExpandEvents(false);
         in.setHandleUserInterrupt(true);
         List<String> persistenHistory = Stream.of(repl.prefs.keys())
@@ -106,9 +113,6 @@
         in.setBellEnabled(true);
         in.setCopyPasteDetection(true);
         in.addCompleter(new Completer() {
-            private String lastTest;
-            private int lastCursor;
-            private boolean allowSmart = false;
             @Override public int complete(String test, int cursor, List<CharSequence> result) {
                 int[] anchor = new int[] {-1};
                 List<Suggestion> suggestions;
@@ -119,16 +123,11 @@
                     suggestions = repl.analysis.completionSuggestions(prefix + test, cursor + prefixLength, anchor);
                     anchor[0] -= prefixLength;
                 }
-                if (!Objects.equals(lastTest, test) || lastCursor != cursor)
-                    allowSmart = true;
-
-                boolean smart = allowSmart &&
+                boolean smart = allowSmart.get() &&
                                 suggestions.stream()
                                            .anyMatch(Suggestion::matchesType);
 
-                lastTest = test;
-                lastCursor = cursor;
-                allowSmart = !allowSmart;
+                allowSmart.set(!allowSmart.get());
 
                 suggestions.stream()
                            .filter(s -> !smart || s.matchesType())
@@ -736,4 +735,57 @@
         }
 
     }
+
+    private static final class CheckCompletionKeyMap extends KeyMap {
+
+        private final KeyMap del;
+        private final AtomicBoolean allowSmart;
+
+        public CheckCompletionKeyMap(KeyMap del, AtomicBoolean allowSmart) {
+            super(del.getName(), del.isViKeyMap());
+            this.del = del;
+            this.allowSmart = allowSmart;
+        }
+
+        @Override
+        public void bind(CharSequence keySeq, Object function) {
+            del.bind(keySeq, function);
+        }
+
+        @Override
+        public void bindIfNotBound(CharSequence keySeq, Object function) {
+            del.bindIfNotBound(keySeq, function);
+        }
+
+        @Override
+        public void from(KeyMap other) {
+            del.from(other);
+        }
+
+        @Override
+        public Object getAnotherKey() {
+            return del.getAnotherKey();
+        }
+
+        @Override
+        public Object getBound(CharSequence keySeq) {
+            Object res = del.getBound(keySeq);
+
+            if (res != Operation.COMPLETE) {
+                allowSmart.set(true);
+            }
+
+            return res;
+        }
+
+        @Override
+        public void setBlinkMatchingParen(boolean on) {
+            del.setBlinkMatchingParen(on);
+        }
+
+        @Override
+        public String toString() {
+            return "check: " + del.toString();
+        }
+    }
 }