groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pa...@apache.org
Subject [groovy] branch master updated: GROOVY-9208: Adapt the groovysh with the new parser Parrot (closes #983)
Date Tue, 30 Jul 2019 23:24:50 GMT
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new faa80fd  GROOVY-9208: Adapt the groovysh with the new parser Parrot (closes #983)
faa80fd is described below

commit faa80fdfcbade6fb0f6df4a5ad03368dd495d23b
Author: Paul King <paulk@asert.com.au>
AuthorDate: Wed Jul 24 21:51:09 2019 +1000

    GROOVY-9208: Adapt the groovysh with the new parser Parrot (closes #983)
---
 .../groovy/groovysh/InteractiveShellRunner.groovy  |  50 ++++--
 .../completion/CustomClassSyntaxCompleter.groovy   |   1 +
 .../completion/GroovySyntaxCompleter.groovy        |   1 +
 .../groovysh/completion/IdentifierCompleter.groovy |   1 +
 .../completion/ImportsSyntaxCompleter.groovy       |   1 +
 .../completion/InfixKeywordSyntaxCompleter.groovy  |   3 +-
 .../completion/KeywordSyntaxCompleter.groovy       |   1 +
 .../groovysh/completion/ReflectionCompleter.groovy |   1 +
 .../completion/VariableSyntaxCompleter.groovy      |   1 +
 .../{ => antlr4}/CustomClassSyntaxCompleter.groovy |   6 +-
 .../{ => antlr4}/GroovySyntaxCompleter.groovy      | 186 +++++++++----------
 .../{ => antlr4}/IdentifierCompleter.groovy        |   6 +-
 .../{ => antlr4}/ImportsSyntaxCompleter.groovy     |   7 +-
 .../InfixKeywordSyntaxCompleter.groovy             |  10 +-
 .../{ => antlr4}/KeywordSyntaxCompleter.groovy     |   8 +-
 .../{ => antlr4}/ReflectionCompleter.groovy        | 200 ++++++++++++++-------
 .../{ => antlr4}/VariableSyntaxCompleter.groovy    |   6 +-
 .../tools/shell/InteractiveShellRunner.groovy      |   1 +
 18 files changed, 298 insertions(+), 192 deletions(-)

diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/InteractiveShellRunner.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/InteractiveShellRunner.groovy
index 80e385c..fdb446e 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/InteractiveShellRunner.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/InteractiveShellRunner.groovy
@@ -23,17 +23,19 @@ import jline.console.completer.AggregateCompleter
 import jline.console.completer.CandidateListCompletionHandler
 import jline.console.completer.CompletionHandler
 import jline.console.history.FileHistory
-import org.apache.groovy.groovysh.completion.CustomClassSyntaxCompleter
 import org.apache.groovy.groovysh.completion.FileNameCompleter
-import org.apache.groovy.groovysh.completion.GroovySyntaxCompleter
-import org.apache.groovy.groovysh.completion.ImportsSyntaxCompleter
-import org.apache.groovy.groovysh.completion.KeywordSyntaxCompleter
-import org.apache.groovy.groovysh.completion.ReflectionCompleter
-import org.apache.groovy.groovysh.completion.VariableSyntaxCompleter
+//import org.apache.groovy.groovysh.completion.GroovySyntaxCompleter
+//import org.apache.groovy.groovysh.completion.ImportsSyntaxCompleter
+//import org.apache.groovy.groovysh.completion.KeywordSyntaxCompleter
+//import org.apache.groovy.groovysh.completion.ReflectionCompleter
+//import org.apache.groovy.groovysh.completion.VariableSyntaxCompleter
 import org.apache.groovy.groovysh.util.WrappedInputStream
+import org.codehaus.groovy.tools.shell.IO
 import org.codehaus.groovy.tools.shell.util.Logger
 import org.codehaus.groovy.tools.shell.util.Preferences
 
+import static org.apache.groovy.util.SystemUtil.getSystemPropertySafe
+
 /**
  * Support for running a {@link Shell} interactively using the JLine library.
  */
@@ -68,16 +70,36 @@ class InteractiveShellRunner extends ShellRunner implements Runnable {
         this.completer = new CommandsMultiCompleter()
         reader.addCompleter(this.completer)
 
-        CustomClassSyntaxCompleter classnameCompleter = new CustomClassSyntaxCompleter(shell)
+        def antlr4 = Boolean.parseBoolean(getSystemPropertySafe("groovy.antlr4", "true"))
+
+        def reflectionCompleter = antlr4 ?
+                new org.apache.groovy.groovysh.completion.antlr4.ReflectionCompleter(shell) :
+                new org.apache.groovy.groovysh.completion.ReflectionCompleter(shell)
 
-        reader.addCompleter(new GroovySyntaxCompleter(shell,
-                new ReflectionCompleter(shell),
+        def classnameCompleter = antlr4 ?
+                new org.apache.groovy.groovysh.completion.antlr4.CustomClassSyntaxCompleter(shell) :
+                new org.apache.groovy.groovysh.completion.CustomClassSyntaxCompleter(shell)
+
+        def identifierCompleters = antlr4 ? [
+                new org.apache.groovy.groovysh.completion.antlr4.KeywordSyntaxCompleter(),
+                new org.apache.groovy.groovysh.completion.antlr4.VariableSyntaxCompleter(shell),
+                classnameCompleter,
+                new org.apache.groovy.groovysh.completion.antlr4.ImportsSyntaxCompleter(shell),
+        ] : [
+                new org.apache.groovy.groovysh.completion.KeywordSyntaxCompleter(),
+                new org.apache.groovy.groovysh.completion.VariableSyntaxCompleter(shell),
                 classnameCompleter,
-                [new KeywordSyntaxCompleter(),
-                 new VariableSyntaxCompleter(shell),
-                 classnameCompleter,
-                 new ImportsSyntaxCompleter(shell)],
-                new FileNameCompleter(false)))
+                new org.apache.groovy.groovysh.completion.ImportsSyntaxCompleter(shell),
+        ]
+
+        def filenameCompleter = new FileNameCompleter(false)
+
+        def completerArgs = [shell, reflectionCompleter, classnameCompleter, identifierCompleters, filenameCompleter]
+
+        reader.addCompleter(antlr4 ?
+                new org.apache.groovy.groovysh.completion.antlr4.GroovySyntaxCompleter(*completerArgs) :
+                new org.apache.groovy.groovysh.completion.GroovySyntaxCompleter(*completerArgs)
+        )
     }
 
     @Override
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/CustomClassSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/CustomClassSyntaxCompleter.groovy
index 07efae7..e26657c 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/CustomClassSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/CustomClassSyntaxCompleter.groovy
@@ -24,6 +24,7 @@ import org.codehaus.groovy.antlr.GroovySourceToken
 /**
  * Completer completing classes defined in the shell
  */
+@Deprecated
 class CustomClassSyntaxCompleter implements IdentifierCompleter {
 
     private final Groovysh shell
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/GroovySyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/GroovySyntaxCompleter.groovy
index a8179aa..3d383a4 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/GroovySyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/GroovySyntaxCompleter.groovy
@@ -63,6 +63,7 @@ import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.SPREAD_DOT
  * Implements the Completer interface to provide completions for
  * GroovyShell by tokenizing the buffer and invoking other classes depending on the tokens found.
  */
+@Deprecated
 class GroovySyntaxCompleter implements Completer {
 
     protected final static Logger LOG = Logger.create(GroovySyntaxCompleter)
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/IdentifierCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/IdentifierCompleter.groovy
index c2d7042..2541618 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/IdentifierCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/IdentifierCompleter.groovy
@@ -25,6 +25,7 @@ import org.codehaus.groovy.antlr.GroovySourceToken
  * (Class, variable, keyword, method, ...)
  * Similar to JLine Completer, but adapted for usage in GroovySyntaxCompleter
  */
+@Deprecated
 interface IdentifierCompleter {
 
     /**
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ImportsSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ImportsSyntaxCompleter.groovy
index b4a77f7..410b4c7 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ImportsSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ImportsSyntaxCompleter.groovy
@@ -25,6 +25,7 @@ import org.codehaus.groovy.control.ResolveVisitor
 /**
  * Completer completing imported classnames
  */
+@Deprecated
 class ImportsSyntaxCompleter implements IdentifierCompleter {
 
     final Groovysh shell
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/InfixKeywordSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/InfixKeywordSyntaxCompleter.groovy
index 8780ca4..ab72c3c 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/InfixKeywordSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/InfixKeywordSyntaxCompleter.groovy
@@ -23,6 +23,7 @@ import org.codehaus.groovy.antlr.GroovySourceToken
 /**
  * Completer completing groovy keywords that appear after identifiers
  */
+@Deprecated
 class InfixKeywordSyntaxCompleter implements IdentifierCompleter {
 
     // INFIX keywords can only occur after identifiers
@@ -31,7 +32,7 @@ class InfixKeywordSyntaxCompleter implements IdentifierCompleter {
             'instanceof',
             'extends',
             'implements',
-            ]
+    ]
 
     @Override
     boolean complete(final List<GroovySourceToken> tokens, final List<CharSequence> candidates) {
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/KeywordSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/KeywordSyntaxCompleter.groovy
index bcfaa3c..9251b78 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/KeywordSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/KeywordSyntaxCompleter.groovy
@@ -23,6 +23,7 @@ import org.codehaus.groovy.antlr.GroovySourceToken
 /**
  * Completer completing Groovy keywords and special functions
  */
+@Deprecated
 class KeywordSyntaxCompleter implements IdentifierCompleter {
 
     private static final String[] KEYWORDS = [
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ReflectionCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ReflectionCompleter.groovy
index 023309b..af23e2a 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ReflectionCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ReflectionCompleter.groovy
@@ -37,6 +37,7 @@ import java.util.regex.Pattern
  * Does not quite respect the contract of IdentifierCompleter, as last Token may be a dot or not,
  * thus also returns as int the cursor position.
  */
+@Deprecated
 class ReflectionCompleter implements GroovyTokenTypes {
 
     private static final NavigablePropertiesCompleter PROPERTIES_COMPLETER = new NavigablePropertiesCompleter()
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/VariableSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/VariableSyntaxCompleter.groovy
index edd339c..6d1743a 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/VariableSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/VariableSyntaxCompleter.groovy
@@ -25,6 +25,7 @@ import org.codehaus.groovy.runtime.MethodClosure
 /**
  * Completer completing variable and method names from known variables in the shell
  */
+@Deprecated
 class VariableSyntaxCompleter implements IdentifierCompleter {
 
     final Groovysh shell
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/CustomClassSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/CustomClassSyntaxCompleter.groovy
similarity index 89%
copy from subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/CustomClassSyntaxCompleter.groovy
copy to subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/CustomClassSyntaxCompleter.groovy
index 07efae7..4577b9c 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/CustomClassSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/CustomClassSyntaxCompleter.groovy
@@ -16,10 +16,10 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.groovy.groovysh.completion
+package org.apache.groovy.groovysh.completion.antlr4
 
+import org.antlr.v4.runtime.Token
 import org.apache.groovy.groovysh.Groovysh
-import org.codehaus.groovy.antlr.GroovySourceToken
 
 /**
  * Completer completing classes defined in the shell
@@ -33,7 +33,7 @@ class CustomClassSyntaxCompleter implements IdentifierCompleter {
     }
 
     @Override
-    boolean complete(final List<GroovySourceToken> tokens, final List<CharSequence> candidates) {
+    boolean complete(final List<Token> tokens, final List<CharSequence> candidates) {
         String prefix = tokens.last().text
         boolean foundMatch = false
         Class[] classes = shell.interp.classLoader.loadedClasses
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/GroovySyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/GroovySyntaxCompleter.groovy
similarity index 68%
copy from subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/GroovySyntaxCompleter.groovy
copy to subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/GroovySyntaxCompleter.groovy
index a8179aa..d1b5a1e 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/GroovySyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/GroovySyntaxCompleter.groovy
@@ -16,48 +16,48 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.groovy.groovysh.completion
+package org.apache.groovy.groovysh.completion.antlr4
 
-import antlr.TokenStreamException
 import groovy.transform.TupleConstructor
 import jline.console.completer.Completer
 import jline.internal.Configuration
+import org.antlr.v4.runtime.CharStream
+import org.antlr.v4.runtime.CharStreams
+import org.antlr.v4.runtime.CommonTokenStream
+import org.antlr.v4.runtime.ConsoleErrorListener
+import org.antlr.v4.runtime.Token
 import org.apache.groovy.groovysh.CommandRegistry
 import org.apache.groovy.groovysh.Groovysh
-import org.codehaus.groovy.antlr.GroovySourceToken
-import org.codehaus.groovy.antlr.SourceBuffer
-import org.codehaus.groovy.antlr.UnicodeEscapingReader
-import org.codehaus.groovy.antlr.parser.GroovyLexer
+import org.apache.groovy.groovysh.completion.BackslashEscapeCompleter
+import org.apache.groovy.groovysh.completion.FileNameCompleter
+import org.apache.groovy.parser.antlr4.GroovyLangLexer
 import org.codehaus.groovy.tools.shell.util.Logger
 
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.DOT
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.EOF
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.IDENT
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_as
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_boolean
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_byte
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_catch
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_char
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_class
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_def
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_double
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_enum
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_false
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_finally
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_float
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_import
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_instanceof
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_int
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_interface
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_long
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_package
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_short
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_this
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_true
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_try
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.LITERAL_void
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.OPTIONAL_DOT
-import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.SPREAD_DOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.AS
+import static org.apache.groovy.parser.antlr4.GroovyLexer.BooleanLiteral
+import static org.apache.groovy.parser.antlr4.GroovyLexer.BuiltInPrimitiveType
+import static org.apache.groovy.parser.antlr4.GroovyLexer.CATCH
+import static org.apache.groovy.parser.antlr4.GroovyLexer.CLASS
+import static org.apache.groovy.parser.antlr4.GroovyLexer.CapitalizedIdentifier
+import static org.apache.groovy.parser.antlr4.GroovyLexer.DEF
+import static org.apache.groovy.parser.antlr4.GroovyLexer.DOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.ENUM
+import static org.apache.groovy.parser.antlr4.GroovyLexer.EOF
+import static org.apache.groovy.parser.antlr4.GroovyLexer.FINALLY
+import static org.apache.groovy.parser.antlr4.GroovyLexer.IMPORT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.INSTANCEOF
+import static org.apache.groovy.parser.antlr4.GroovyLexer.INTERFACE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.Identifier
+import static org.apache.groovy.parser.antlr4.GroovyLexer.METHOD_POINTER
+import static org.apache.groovy.parser.antlr4.GroovyLexer.METHOD_REFERENCE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.NOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.NOT_INSTANCEOF
+import static org.apache.groovy.parser.antlr4.GroovyLexer.PACKAGE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.SAFE_DOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.SPREAD_DOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.THIS
+import static org.apache.groovy.parser.antlr4.GroovyLexer.TRY
+import static org.apache.groovy.parser.antlr4.GroovyLexer.VOID
 
 /**
  * Implements the Completer interface to provide completions for
@@ -116,7 +116,7 @@ class GroovySyntaxCompleter implements Completer {
         }
         // complete given the context of the whole buffer, not just last line
         // Build a single string for the lexer
-        List<GroovySourceToken> tokens = []
+        List<Token> tokens = []
         try {
             if (!tokenizeBuffer(bufferLine.substring(0, cursor), shell.buffers.current(), tokens)) {
                 return -1
@@ -157,13 +157,13 @@ class GroovySyntaxCompleter implements Completer {
         }
         if (completionCase == CompletionCase.SECOND_IDENT) {
             if (infixCompleter.complete(tokens, candidates)) {
-                return tokens.last().column - 1
+                return tokens.last().startIndex
             }
             return -1
         }
         if (completionCase == CompletionCase.INSTANCEOF) {
             if (classnameCompleter.complete(tokens, candidates)) {
-                return tokens.last().column - 1
+                return tokens.last().startIndex
             }
             return -1
         }
@@ -188,24 +188,24 @@ class GroovySyntaxCompleter implements Completer {
         return result
     }
 
-    static CompletionCase getCompletionCase(final List<GroovySourceToken> tokens) {
-        GroovySourceToken currentToken = tokens[-1]
+    static CompletionCase getCompletionCase(final List<Token> tokens) {
+        Token currentToken = tokens[-1]
 
         // now look at last 2 tokens to decide whether we are in a completion situation at all
-        if (currentToken.type == IDENT) {
+        if (currentToken.type == Identifier || currentToken.type == CapitalizedIdentifier) {
             // cursor is on identifier, use it as prefix and check whether it follows a dot
 
             if (tokens.size() == 1) {
                 return CompletionCase.NO_DOT_PREFIX
             }
-            GroovySourceToken previousToken = tokens[-2]
-            if (previousToken.type == DOT || previousToken.type == OPTIONAL_DOT) {
+            Token previousToken = tokens[-2]
+            if (previousToken.type == DOT || previousToken.type == SAFE_DOT) {
                 // we have a dot, so need to evaluate the statement up to the dot for completion
                 if (tokens.size() < 3) {
                     return CompletionCase.NO_COMPLETION
                 }
                 return CompletionCase.PREFIX_AFTER_DOT
-            } else if (previousToken.type == SPREAD_DOT) {
+            } else if (previousToken.type == SPREAD_DOT || previousToken.type == METHOD_POINTER || previousToken.type == METHOD_REFERENCE) {
                 // we have a dot, so need to evaluate the statement up to the dot for completion
                 if (tokens.size() < 3) {
                     return CompletionCase.NO_COMPLETION
@@ -215,30 +215,33 @@ class GroovySyntaxCompleter implements Completer {
                 // no dot, so we complete a varname, classname, or similar
                 switch (previousToken.type) {
                 // if any of these is before, no useful completion possible in this completer
-                    case LITERAL_import:
-                    case LITERAL_class:
-                    case LITERAL_interface:
-                    case LITERAL_enum:
-                    case LITERAL_def:
-                    case LITERAL_void:
-                    case LITERAL_boolean:
-                    case LITERAL_byte:
-                    case LITERAL_char:
-                    case LITERAL_short:
-                    case LITERAL_int:
-                    case LITERAL_float:
-                    case LITERAL_long:
-                    case LITERAL_double:
-                    case LITERAL_package:
-                    case LITERAL_true:
-                    case LITERAL_false:
-                    case LITERAL_as:
-                    case LITERAL_this:
-                    case LITERAL_try:
-                    case LITERAL_finally:
-                    case LITERAL_catch:
+                    case IMPORT:
+                    case CLASS:
+                    case INTERFACE:
+                    case ENUM:
+                    case DEF:
+                    case VOID:
+                    case BuiltInPrimitiveType:
+//                    case LITERAL_byte:
+//                    case LITERAL_char:
+//                    case LITERAL_short:
+//                    case LITERAL_int:
+//                    case LITERAL_float:
+//                    case LITERAL_long:
+//                    case LITERAL_double:
+                    case PACKAGE:
+                    case BooleanLiteral:
+//                    case LITERAL_true:
+//                    case LITERAL_false:
+                    case AS:
+                    case THIS:
+                    case TRY:
+                    case FINALLY:
+                    case CATCH:
                         return CompletionCase.NO_COMPLETION
-                    case IDENT:
+                    case NOT: // just for !in and !instanceof; maybe needs special case
+                    case CapitalizedIdentifier:
+                    case Identifier:
                         // identifiers following each other could mean Declaration (no completion) or closure invocation
                         // closure invocation too complex for now to complete
                         return CompletionCase.SECOND_IDENT
@@ -247,33 +250,33 @@ class GroovySyntaxCompleter implements Completer {
                 }
             }
 
-        } else if (currentToken.type == DOT || currentToken.type == OPTIONAL_DOT) {
+        } else if (currentToken.type == DOT || currentToken.type == SAFE_DOT) {
             // cursor is on dot, so need to evaluate the statement up to the dot for completion
             if (tokens.size() == 1) {
                 return CompletionCase.NO_COMPLETION
             }
             return CompletionCase.DOT_LAST
-        } else if (currentToken.type == SPREAD_DOT) {
+        } else if (currentToken.type == SPREAD_DOT || currentToken.type == METHOD_REFERENCE || currentToken.type == METHOD_POINTER) {
             // cursor is on spread-dot, so need to evaluate the statement up to the dot for completion
             if (tokens.size() == 1) {
                 return CompletionCase.NO_COMPLETION
             }
             return CompletionCase.SPREAD_DOT_LAST
-        } else if (currentToken.type == LITERAL_instanceof) {
+        } else if (currentToken.type == INSTANCEOF || currentToken.type == NOT_INSTANCEOF) {
             return CompletionCase.INSTANCEOF
         } else {
-            LOG.debug('Untreated toke type: ' + currentToken.type)
+            LOG.debug('Unhandled token type: ' + currentToken.type)
         }
         return CompletionCase.NO_COMPLETION
     }
 
-    int completeIdentifier(final List<GroovySourceToken> tokens, final List<CharSequence> candidates) {
+    int completeIdentifier(final List<Token> tokens, final List<CharSequence> candidates) {
         boolean foundMatches = false
         for (IdentifierCompleter completer : identifierCompleters) {
             foundMatches |= completer.complete(tokens, candidates)
         }
         if (foundMatches) {
-            return tokens.last().column - 1
+            return tokens.last().startIndex
         }
         return -1
     }
@@ -292,11 +295,13 @@ class GroovySyntaxCompleter implements Completer {
         return false
     }
 
-    static GroovyLexer createGroovyLexer(final String src) {
-        Reader unicodeReader = new UnicodeEscapingReader(new StringReader(src), new SourceBuffer())
-        GroovyLexer lexer = new GroovyLexer(unicodeReader)
-        unicodeReader.setLexer(lexer)
-        return lexer
+    static createTokenStream(String text) {
+        CharStream charStream = CharStreams.fromReader(new StringReader(text))
+        GroovyLangLexer lexer = new GroovyLangLexer(charStream)
+        lexer.removeErrorListener(ConsoleErrorListener.INSTANCE)
+        def tokenStream = new CommonTokenStream(lexer)
+        tokenStream.fill()
+        return tokenStream
     }
 
     @TupleConstructor
@@ -321,24 +326,24 @@ class GroovySyntaxCompleter implements Completer {
      */
     static boolean tokenizeBuffer(final String bufferLine,
                                   final List<String> previousLines,
-                                  final List<GroovySourceToken> result) {
-        GroovyLexer groovyLexer
+                                  final List<Token> result) {
+        def tokenStream
         if (previousLines.size() > 0) {
             StringBuilder src = new StringBuilder()
             for (String line : previousLines) {
                 src.append(line).append('\n')
             }
             src.append(bufferLine)
-            groovyLexer = createGroovyLexer(src.toString())
+            tokenStream = createTokenStream(src.toString()).getTokens().iterator()
         } else {
-            groovyLexer = createGroovyLexer(bufferLine)
+            tokenStream = createTokenStream(bufferLine).getTokens().iterator()
         }
-        // Build a list of tokens using a GroovyLexer
-        GroovySourceToken nextToken
-        GroovySourceToken lastToken
+        // Build a list of tokens
+        Token nextToken
+        Token lastToken
         while (true) {
             try {
-                nextToken = groovyLexer.nextToken() as GroovySourceToken
+                nextToken = tokenStream.next() as Token
                 if (nextToken.type == EOF) {
                     if (!result.isEmpty() && nextToken.line > result.last().line) {
                         // no completion if EOF line has no tokens
@@ -348,14 +353,14 @@ class GroovySyntaxCompleter implements Completer {
                 }
                 result << nextToken
                 lastToken = nextToken
-            } catch (TokenStreamException e) {
+            } catch (Exception e) {
+                // TODO this whole section needs a rework for antlr4
                 // getting the next token failed, possibly due to unclosed quotes; investigate rest of the line to confirm
                 if (lastToken != null) {
                     String restline = bufferLine.substring(lastToken.columnLast - 1)
                     int leadingBlanks = restline.find('^[ ]*').length()
                     if (restline) {
                         String remainder = restline.substring(leadingBlanks)
-                        //System.err.println "|" + remainder + "|"
                         // Exception with following quote either means we're in String or at end of GString.
                         String openDelim = STRING_STARTERS.find { remainder.startsWith(it) }
                         if (openDelim && previousLines.size() + 1 == lastToken.line) {
@@ -364,9 +369,10 @@ class GroovySyntaxCompleter implements Completer {
                     }
                 }
                 return false
-            } catch (NullPointerException e) {
-                // this can happen when e.g. a string as not closed
-                return false
+//            } catch (NullPointerException e) {
+//                // this can happen when e.g. a string as not closed
+//                new File('/tmp/groovysh_log.txt') << e.message << '\n'
+//                return false
             }
         }
         return !result.empty
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/IdentifierCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/IdentifierCompleter.groovy
similarity index 87%
copy from subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/IdentifierCompleter.groovy
copy to subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/IdentifierCompleter.groovy
index c2d7042..96a97bc 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/IdentifierCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/IdentifierCompleter.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.groovy.groovysh.completion
+package org.apache.groovy.groovysh.completion.antlr4
 
-import org.codehaus.groovy.antlr.GroovySourceToken
+import org.antlr.v4.runtime.Token
 
 /**
  * Interface for classes that complete identifier tokens within a groovy Statement
@@ -33,6 +33,6 @@ interface IdentifierCompleter {
      * @param candidates
      * @return
      */
-    boolean complete(List<GroovySourceToken> tokens, List<CharSequence> candidates)
+    boolean complete(List<Token> tokens, List<CharSequence> candidates)
 
 }
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ImportsSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ImportsSyntaxCompleter.groovy
similarity index 95%
copy from subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ImportsSyntaxCompleter.groovy
copy to subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ImportsSyntaxCompleter.groovy
index b4a77f7..f675788 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ImportsSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ImportsSyntaxCompleter.groovy
@@ -16,10 +16,11 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.groovy.groovysh.completion
+package org.apache.groovy.groovysh.completion.antlr4
 
+import org.antlr.v4.runtime.Token
 import org.apache.groovy.groovysh.Groovysh
-import org.codehaus.groovy.antlr.GroovySourceToken
+import org.apache.groovy.groovysh.completion.ReflectionCompleter
 import org.codehaus.groovy.control.ResolveVisitor
 
 /**
@@ -42,7 +43,7 @@ class ImportsSyntaxCompleter implements IdentifierCompleter {
     }
 
     @Override
-    boolean complete(final List<GroovySourceToken> tokens, final List<CharSequence> candidates) {
+    boolean complete(final List<Token> tokens, final List<CharSequence> candidates) {
         String prefix = tokens.last().getText()
         boolean foundMatch = findMatchingPreImportedClasses(prefix, candidates)
         for (String importSpec in shell.imports) {
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/InfixKeywordSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/InfixKeywordSyntaxCompleter.groovy
similarity index 86%
copy from subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/InfixKeywordSyntaxCompleter.groovy
copy to subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/InfixKeywordSyntaxCompleter.groovy
index 8780ca4..4b016b4 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/InfixKeywordSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/InfixKeywordSyntaxCompleter.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.groovy.groovysh.completion
+package org.apache.groovy.groovysh.completion.antlr4
 
-import org.codehaus.groovy.antlr.GroovySourceToken
+import org.antlr.v4.runtime.Token
 
 /**
  * Completer completing groovy keywords that appear after identifiers
@@ -29,12 +29,14 @@ class InfixKeywordSyntaxCompleter implements IdentifierCompleter {
     private static final String[] INFIX_KEYWORDS = [
             'in',
             'instanceof',
+            '!in',
+            '!instanceof',
             'extends',
             'implements',
-            ]
+    ]
 
     @Override
-    boolean complete(final List<GroovySourceToken> tokens, final List<CharSequence> candidates) {
+    boolean complete(final List<Token> tokens, final List<CharSequence> candidates) {
         String prefix = tokens.last().text
         boolean foundMatch = false
         for (String varName in INFIX_KEYWORDS) {
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/KeywordSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/KeywordSyntaxCompleter.groovy
similarity index 94%
copy from subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/KeywordSyntaxCompleter.groovy
copy to subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/KeywordSyntaxCompleter.groovy
index bcfaa3c..294b265 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/KeywordSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/KeywordSyntaxCompleter.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.groovy.groovysh.completion
+package org.apache.groovy.groovysh.completion.antlr4
 
-import org.codehaus.groovy.antlr.GroovySourceToken
+import org.antlr.v4.runtime.Token
 
 /**
  * Completer completing Groovy keywords and special functions
@@ -63,7 +63,7 @@ class KeywordSyntaxCompleter implements IdentifierCompleter {
             'transient',
             //'true', // value
             //'try {', //special
-            'void', 'volatile'
+            'var', 'void', 'volatile'
             //'while (' // special
     ]
 
@@ -93,7 +93,7 @@ class KeywordSyntaxCompleter implements IdentifierCompleter {
     ]
 
     @Override
-    boolean complete(final List<GroovySourceToken> tokens, final List<CharSequence> candidates) {
+    boolean complete(final List<Token> tokens, final List<CharSequence> candidates) {
         String prefix = tokens.last().text
         boolean foundMatch = false
         for (String varName in KEYWORDS) {
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ReflectionCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ReflectionCompleter.groovy
similarity index 77%
copy from subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ReflectionCompleter.groovy
copy to subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ReflectionCompleter.groovy
index 023309b..d49c4bf 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/ReflectionCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ReflectionCompleter.groovy
@@ -16,11 +16,12 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.groovy.groovysh.completion
+package org.apache.groovy.groovysh.completion.antlr4
 
+import org.antlr.v4.runtime.Token
 import org.apache.groovy.groovysh.Groovysh
-import org.codehaus.groovy.antlr.GroovySourceToken
-import org.codehaus.groovy.antlr.parser.GroovyTokenTypes
+import org.apache.groovy.groovysh.completion.NavigablePropertiesCompleter
+import org.apache.groovy.groovysh.completion.ReflectionCompletionCandidate
 import org.codehaus.groovy.control.MultipleCompilationErrorsException
 import org.codehaus.groovy.runtime.InvokerHelper
 import org.codehaus.groovy.tools.shell.util.Preferences
@@ -32,12 +33,62 @@ import java.lang.reflect.Method
 import java.lang.reflect.Modifier
 import java.util.regex.Pattern
 
+import static org.apache.groovy.parser.antlr4.GroovyLexer.ADD
+import static org.apache.groovy.parser.antlr4.GroovyLexer.ADD_ASSIGN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.AND
+import static org.apache.groovy.parser.antlr4.GroovyLexer.AND_ASSIGN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.ASSIGN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.BITAND
+import static org.apache.groovy.parser.antlr4.GroovyLexer.BITNOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.BITOR
+import static org.apache.groovy.parser.antlr4.GroovyLexer.BooleanLiteral
+import static org.apache.groovy.parser.antlr4.GroovyLexer.BuiltInPrimitiveType
+import static org.apache.groovy.parser.antlr4.GroovyLexer.COLON
+import static org.apache.groovy.parser.antlr4.GroovyLexer.COMMA
+import static org.apache.groovy.parser.antlr4.GroovyLexer.CapitalizedIdentifier
+import static org.apache.groovy.parser.antlr4.GroovyLexer.DIV
+import static org.apache.groovy.parser.antlr4.GroovyLexer.DIV_ASSIGN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.DOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.EQUAL
+import static org.apache.groovy.parser.antlr4.GroovyLexer.GE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.GStringBegin
+import static org.apache.groovy.parser.antlr4.GroovyLexer.GT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.Identifier
+import static org.apache.groovy.parser.antlr4.GroovyLexer.IN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.INSTANCEOF
+import static org.apache.groovy.parser.antlr4.GroovyLexer.LBRACE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.LBRACK
+import static org.apache.groovy.parser.antlr4.GroovyLexer.LPAREN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.LE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.LT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.METHOD_POINTER
+import static org.apache.groovy.parser.antlr4.GroovyLexer.METHOD_REFERENCE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.MUL
+import static org.apache.groovy.parser.antlr4.GroovyLexer.MUL_ASSIGN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.NOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.NOTEQUAL
+import static org.apache.groovy.parser.antlr4.GroovyLexer.OR
+import static org.apache.groovy.parser.antlr4.GroovyLexer.OR_ASSIGN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.RANGE_EXCLUSIVE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.RANGE_INCLUSIVE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.RBRACK
+import static org.apache.groovy.parser.antlr4.GroovyLexer.RPAREN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.SAFE_DOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.SEMI
+import static org.apache.groovy.parser.antlr4.GroovyLexer.SPACESHIP
+import static org.apache.groovy.parser.antlr4.GroovyLexer.SPREAD_DOT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.StringLiteral
+import static org.apache.groovy.parser.antlr4.GroovyLexer.SUB
+import static org.apache.groovy.parser.antlr4.GroovyLexer.SUB_ASSIGN
+import static org.apache.groovy.parser.antlr4.GroovyLexer.XOR
+import static org.apache.groovy.parser.antlr4.GroovyLexer.XOR_ASSIGN
+
 /**
  * Completes fields and methods of Classes or instances.
  * Does not quite respect the contract of IdentifierCompleter, as last Token may be a dot or not,
  * thus also returns as int the cursor position.
  */
-class ReflectionCompleter implements GroovyTokenTypes {
+class ReflectionCompleter {
 
     private static final NavigablePropertiesCompleter PROPERTIES_COMPLETER = new NavigablePropertiesCompleter()
     private static final Pattern BEAN_ACCESSOR_PATTERN = ~'^(get|set|is)[A-Z].*'
@@ -53,19 +104,19 @@ class ReflectionCompleter implements GroovyTokenTypes {
         this.shell = shell
     }
 
-    int complete(final List<GroovySourceToken> tokens, final List<CharSequence> candidates) {
-        GroovySourceToken currentElementToken = null
-        GroovySourceToken dotToken
-        List<GroovySourceToken> previousTokens
+    int complete(final List<Token> tokens, final List<CharSequence> candidates) {
+        Token currentElementToken = null
+        Token dotToken
+        List<Token> previousTokens
         if (tokens.size() < 2) {
-            throw new IllegalArgumentException('must be invoked with at least 2 tokens, one of which is dot' + tokens*.text)
+            throw new IllegalArgumentException('Must be invoked with at least 2 tokens, one of which is a dot-like operator: ' + tokens*.text)
         }
-        if (tokens.last().type == DOT || tokens.last().type == OPTIONAL_DOT || tokens.last().type == SPREAD_DOT) {
+        if (tokens.last().type == DOT || tokens.last().type == SAFE_DOT || tokens.last().type == SPREAD_DOT || tokens.last().type == METHOD_POINTER || tokens.last().type == METHOD_REFERENCE) {
             dotToken = tokens.last()
             previousTokens = tokens[0..-2]
         } else {
-            if (tokens[-2].type != DOT && tokens[-2].type != OPTIONAL_DOT && tokens[-2].type != SPREAD_DOT) {
-                throw new IllegalArgumentException('must be invoked with token list with dot at last position or one position before' + tokens*.text)
+            if (tokens[-2].type != DOT && tokens[-2].type != SAFE_DOT && tokens[-2].type != SPREAD_DOT && tokens[-2].type != METHOD_POINTER && tokens[-2].type != METHOD_REFERENCE) {
+                throw new IllegalArgumentException('Must be invoked with token list with dot-like operator at last position or one position before: ' + tokens*.text)
             }
             currentElementToken = tokens.last()
             dotToken = tokens[-2]
@@ -103,10 +154,11 @@ class ReflectionCompleter implements GroovyTokenTypes {
     private int completeInstanceMembers(final Object instanceOrClass,
                                         final String identifierPrefix,
                                         final List<CharSequence> candidates,
-                                        final GroovySourceToken currentElementToken,
-                                        final GroovySourceToken dotToken) {
+                                        final Token currentElementToken,
+                                        final Token dotToken) {
         // look for public methods/fields that match the prefix
-        Collection<ReflectionCompletionCandidate> myCandidates = getPublicFieldsAndMethods(instanceOrClass, identifierPrefix)
+        def methodRef = dotToken.type == METHOD_POINTER || dotToken.type == METHOD_REFERENCE
+        Collection<ReflectionCompletionCandidate> myCandidates = getPublicFieldsAndMethods(instanceOrClass, identifierPrefix, methodRef)
 
         boolean showAllMethods = (identifierPrefix.length() >= Integer.valueOf(Preferences.get(Groovysh.METACLASS_COMPLETION_PREFIX_LENGTH_PREFERENCE_KEY, '3')))
         // Also add metaclass methods if prefix is long enough (user would usually not care about those)
@@ -127,6 +179,15 @@ class ReflectionCompleter implements GroovyTokenTypes {
 
         if (myCandidates.size() > 0) {
             myCandidates = myCandidates.sort()
+            if (methodRef) {
+                // strip braces for :: and .& operators
+                myCandidates = myCandidates.collect { cand ->
+                    def val = cand.value
+                    val = val.endsWith('()') ? val[0..-3] :
+                            (val.endsWith('(') ? val[0..-2] : val)
+                    new ReflectionCompletionCandidate(val, *cand.jAnsiCodes)
+                }
+            }
             if (Boolean.valueOf(Preferences.get(Groovysh.COLORS_PREFERENCE_KEY, 'true'))) {
                 candidates.addAll(myCandidates.collect(
                         { ReflectionCompletionCandidate it ->
@@ -140,10 +201,10 @@ class ReflectionCompleter implements GroovyTokenTypes {
             int lastDot
             // dot could be on previous line
             if (currentElementToken && dotToken.line != currentElementToken.line) {
-                lastDot = currentElementToken.column - 1
+                lastDot = currentElementToken.startIndex
             } else {
-                // Spread-dot has length 2!
-                lastDot = dotToken.column + (dotToken.getText().length() - 1)
+                // Spread-dot/Method-ref/Method-pointer have length 2!
+                lastDot = dotToken.startIndex + dotToken.text.size()
             }
             return lastDot
         }
@@ -157,15 +218,15 @@ class ReflectionCompleter implements GroovyTokenTypes {
      * evaluates it and returns a result. "Simple" means evaluation is known to be
      * side-effect free.
      */
-    Object getInvokerClassOrInstance(final List<GroovySourceToken> groovySourceTokens) {
+    Object getInvokerClassOrInstance(final List<Token> groovySourceTokens) {
         if (!groovySourceTokens
                 || groovySourceTokens.last().type == DOT
-                || groovySourceTokens.last().type == OPTIONAL_DOT) {
+                || groovySourceTokens.last().type == SAFE_DOT) {
             // we expect the list of tokens before a dot.
             return null
         }
         // first, try to detect a sequence of token before the dot that can safely be evaluated.
-        List<GroovySourceToken> invokerTokens = getInvokerTokens(groovySourceTokens)
+        List<Token> invokerTokens = getInvokerTokens(groovySourceTokens)
         if (invokerTokens) {
             try {
                 String instanceRefExpression = tokenListToEvalString(invokerTokens)
@@ -190,7 +251,7 @@ class ReflectionCompleter implements GroovyTokenTypes {
      * @param groovySourceTokens
      * @return
      */
-    static List<GroovySourceToken> getInvokerTokens(final List<GroovySourceToken> groovySourceTokens) {
+    static List<Token> getInvokerTokens(final List<Token> groovySourceTokens) {
         int validIndex = groovySourceTokens.size()
         if (validIndex == 0) {
             return []
@@ -199,15 +260,15 @@ class ReflectionCompleter implements GroovyTokenTypes {
         // to be evaluated later
         // need to collect using Strings, to support evaluation of string literals
         Stack<Integer> expectedOpeners = new Stack<Integer>()
-        GroovySourceToken lastToken = null
+        Token lastToken = null
         outerloop:
-        for (GroovySourceToken loopToken in groovySourceTokens.reverse()) {
+        for (Token loopToken in groovySourceTokens.reverse()) {
             switch (loopToken.type) {
             // a combination of any of these can be evaluated without side effects
             // this just avoids any parentheses,
             // could maybe be extended further if harmless parentheses can be detected .
             // This allows already a lot of powerful simple completions, like [foo: Baz.bar]['foo'].
-                case STRING_LITERAL:
+                case StringLiteral:
                     // must escape String for evaluation, need the original string e.g. for mapping key
                     break
                 case LPAREN:
@@ -234,51 +295,53 @@ class ReflectionCompleter implements GroovyTokenTypes {
                     break
             // tokens which indicate we have reached the beginning of a statement
             // operator tokens (must not be evaluated, as they can have side effects via evil overriding
-                case COMPARE_TO:
+                case SPACESHIP:
                 case EQUAL:
-                case NOT_EQUAL:
+                case NOTEQUAL:
                 case ASSIGN:
                 case GT:
                 case LT:
                 case GE:
                 case LE:
-                case PLUS:
-                case PLUS_ASSIGN:
-                case MINUS:
-                case MINUS_ASSIGN:
-                case STAR:
-                case STAR_ASSIGN:
+                case ADD:
+                case ADD_ASSIGN:
+                case SUB:
+                case SUB_ASSIGN:
+                case MUL:
+                case MUL_ASSIGN:
                 case DIV:
                 case DIV_ASSIGN:
-                case BOR:
-                case BOR_ASSIGN:
-                case BAND:
-                case BAND_ASSIGN:
-                case BXOR:
-                case BXOR_ASSIGN:
-                case BNOT:
-                case LOR:
-                case LAND:
-                case LNOT:
-                case LITERAL_in:
-                case LITERAL_instanceof:
+                case BITOR:
+                case OR_ASSIGN:
+                case BITAND:
+                case AND_ASSIGN:
+                case XOR:
+                case XOR_ASSIGN:
+                case BITNOT:
+                case OR:
+                case AND:
+                case NOT:
+                case IN:
+                case INSTANCEOF:
                     if (expectedOpeners.empty()) {
                         break outerloop
                     }
                     break
             // tokens which indicate we have reached the beginning of a statement
-                case LCURLY:
+                case LBRACE:
                 case SEMI:
-                case STRING_CTOR_START:
+//                case STRING_CTOR_START:
+                case GStringBegin:
                     break outerloop
             // tokens we accept
-                case IDENT:
+                case Identifier:
+                case CapitalizedIdentifier:
                     if (lastToken) {
                         if (lastToken.type == LPAREN) {
                             //Method invocation,must be avoided
                             return []
                         }
-                        if (lastToken.type == IDENT) {
+                        if (lastToken.type == Identifier || lastToken.type == CapitalizedIdentifier) {
                             // could be attempt to invoke closure like 'foo.each bar.baz'
                             return []
                         }
@@ -293,17 +356,19 @@ class ReflectionCompleter implements GroovyTokenTypes {
                         break outerloop
                     }
             // harmless literals
-                case LITERAL_true:
-                case LITERAL_false:
-                case NUM_INT:
-                case NUM_FLOAT:
-                case NUM_LONG:
-                case NUM_DOUBLE:
-                case NUM_BIG_INT:
-                case NUM_BIG_DECIMAL:
-                case MEMBER_POINTER:
+                case BooleanLiteral:
+//                case LITERAL_true:
+//                case LITERAL_false:
+                case BuiltInPrimitiveType:
+//                case NUM_INT:
+//                case NUM_FLOAT:
+//                case NUM_LONG:
+//                case NUM_DOUBLE:
+//                case NUM_BIG_INT:
+//                case NUM_BIG_DECIMAL:
+                case METHOD_POINTER:
                 case DOT:
-                case OPTIONAL_DOT:
+                case SAFE_DOT:
                     break
                 default:
                     return null
@@ -314,10 +379,10 @@ class ReflectionCompleter implements GroovyTokenTypes {
         return groovySourceTokens[(validIndex)..-1]
     }
 
-    static String tokenListToEvalString(final List<GroovySourceToken> groovySourceTokens) {
+    static String tokenListToEvalString(final List<Token> groovySourceTokens) {
         StringBuilder builder = new StringBuilder()
-        for (GroovySourceToken token : groovySourceTokens) {
-            if (token.type == STRING_LITERAL) {
+        for (Token token : groovySourceTokens) {
+            if (token.type == StringLiteral) {
                 builder.append('\'').append(token.text).append('\'')
             } else {
                 builder.append(token.text)
@@ -351,7 +416,7 @@ class ReflectionCompleter implements GroovyTokenTypes {
      * @param prefix the prefix that must be matched
      * @return the list of public methods and fields that begin with the prefix
      */
-    static Collection<ReflectionCompletionCandidate> getPublicFieldsAndMethods(final Object instance, final String prefix) {
+    static Collection<ReflectionCompletionCandidate> getPublicFieldsAndMethods(final Object instance, final String prefix, final boolean all = false) {
         Set<ReflectionCompletionCandidate> rv = new HashSet<ReflectionCompletionCandidate>()
         Class clazz = instance.getClass()
         if (clazz == null) {
@@ -367,13 +432,14 @@ class ReflectionCompleter implements GroovyTokenTypes {
         // render immediate class members bold when completing an instance
         boolean renderBold = !isClass
         // hide static members for instances unless user typed a prefix
-        boolean showStatic = isClass || (prefix.length() >= Integer.valueOf(Preferences.get(Groovysh.METACLASS_COMPLETION_PREFIX_LENGTH_PREFERENCE_KEY, '3')))
+        boolean showStatic = isClass || all || (prefix.length() >= Integer.valueOf(Preferences.get(Groovysh.METACLASS_COMPLETION_PREFIX_LENGTH_PREFERENCE_KEY, '3')))
+        boolean showInstance = !isClass || all
         while (loopclazz != null && loopclazz != Object && loopclazz != GroovyObject) {
-            addClassFieldsAndMethods(loopclazz, showStatic, !isClass, prefix, rv, renderBold)
+            addClassFieldsAndMethods(loopclazz, showStatic, showInstance, prefix, rv, renderBold)
             renderBold = false
             loopclazz = loopclazz.superclass
         }
-        if (clazz.isArray() && !isClass) {
+        if (clazz.isArray() && showInstance) {
             // Arrays are special, these public members cannot be found via Reflection
             for (String member : ['length', 'clone()']) {
                 if (member.startsWith(prefix)) {
@@ -383,7 +449,7 @@ class ReflectionCompleter implements GroovyTokenTypes {
         }
 
         // other completions that are commonly possible with properties
-        if (!isClass) {
+        if (showInstance) {
             Set<String> candidates = new HashSet<String>()
             PROPERTIES_COMPLETER.addCompletions(instance, prefix, candidates)
             rv.addAll(candidates.collect({ String it -> new ReflectionCompletionCandidate(it, AnsiRenderer.Code.MAGENTA.name()) }))
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/VariableSyntaxCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/VariableSyntaxCompleter.groovy
similarity index 91%
copy from subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/VariableSyntaxCompleter.groovy
copy to subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/VariableSyntaxCompleter.groovy
index edd339c..31e3247 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/VariableSyntaxCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/VariableSyntaxCompleter.groovy
@@ -16,10 +16,10 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.groovy.groovysh.completion
+package org.apache.groovy.groovysh.completion.antlr4
 
+import org.antlr.v4.runtime.Token
 import org.apache.groovy.groovysh.Groovysh
-import org.codehaus.groovy.antlr.GroovySourceToken
 import org.codehaus.groovy.runtime.MethodClosure
 
 /**
@@ -34,7 +34,7 @@ class VariableSyntaxCompleter implements IdentifierCompleter {
     }
 
     @Override
-    boolean complete(final List<GroovySourceToken> tokens, final List<CharSequence> candidates) {
+    boolean complete(final List<Token> tokens, final List<CharSequence> candidates) {
         String prefix = tokens.last().text
         Map vars = shell.interp.context.variables
         boolean foundMatch = false
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/InteractiveShellRunner.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/InteractiveShellRunner.groovy
index 11a20ac..de73fde 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/InteractiveShellRunner.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/InteractiveShellRunner.groovy
@@ -30,6 +30,7 @@ import org.codehaus.groovy.tools.shell.completion.ImportsSyntaxCompletor
 import org.codehaus.groovy.tools.shell.completion.KeywordSyntaxCompletor
 import org.codehaus.groovy.tools.shell.completion.ReflectionCompletor
 import org.codehaus.groovy.tools.shell.completion.VariableSyntaxCompletor
+import org.codehaus.groovy.tools.shell.IO
 import org.codehaus.groovy.tools.shell.util.Logger
 import org.codehaus.groovy.tools.shell.util.Preferences
 import org.codehaus.groovy.tools.shell.util.WrappedInputStream


Mime
View raw message