in subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/GroovySyntaxCompleter.groovy [191:271]
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 == 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
}
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 || 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
}
return CompletionCase.PREFIX_AFTER_SPREAD_DOT
} else {
// 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 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 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
default:
return CompletionCase.NO_DOT_PREFIX
}
}
} 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 || 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 == INSTANCEOF || currentToken.type == NOT_INSTANCEOF) {
return CompletionCase.INSTANCEOF
} else {
LOG.debug('Unhandled token type: ' + currentToken.type)
}
return CompletionCase.NO_COMPLETION
}