in src/LanguageServer/Impl/Completion/TopLevelCompletion.cs [97:157]
private static CompletionListOptions GetOptions(Node statement, int index, out IndexSpan? span) {
span = null;
switch (statement) {
// Disallow keywords, unless we're between the end of decorators and the
// end of the "[async] def" keyword.
case FunctionDefinition fd when index > fd.KeywordEndIndex || fd.Decorators != null && index < fd.Decorators.EndIndex:
case ClassDefinition cd when index > cd.KeywordEndIndex || cd.Decorators != null && index < cd.Decorators.EndIndex:
return CompletionListOptions.NoKeywords;
case TryStatementHandler tryStatement when tryStatement.Test is TupleExpression || index >= tryStatement.Test.StartIndex:
return CompletionListOptions.ExceptionsOnly;
// Always allow keywords in non-keyword statements
case ExpressionStatement _:
case ImportStatement _:
case FromImportStatement _:
case null:
return CompletionListOptions.AllKeywords;
// Allow keywords at start of assignment, but not in subsequent names
case AssignmentStatement ss:
var firstAssign = ss.Left?.FirstOrDefault();
return firstAssign == null || index <= firstAssign.EndIndex
? CompletionListOptions.AllKeywords : CompletionListOptions.ExpressionKeywords;
// Allow keywords when we are in another keyword
case Statement s when index <= s.KeywordEndIndex:
var keywordStart = s.KeywordEndIndex - s.KeywordLength;
if (index >= keywordStart) {
span = new IndexSpan(keywordStart, s.KeywordLength);
} else if ((s as IMaybeAsyncStatement)?.IsAsync == true) {
// Must be in the "async" at the start of the keyword
span = new IndexSpan(s.StartIndex, "async".Length);
}
return CompletionListOptions.AllKeywords;
case RaiseStatement raise when raise.ExceptType != null && index >= raise.ExceptType.StartIndex || index > raise.KeywordEndIndex:
return CompletionListOptions.ExpressionKeywords | CompletionListOptions.ExceptionsOnly;
// TryStatementHandler is 'except', but not a Statement subclass
case TryStatementHandler except when index <= except.KeywordEndIndex:
var exceptKeywordStart = except.KeywordEndIndex - except.KeywordLength;
if (index >= exceptKeywordStart) {
span = new IndexSpan(exceptKeywordStart, except.KeywordLength);
}
return CompletionListOptions.AllKeywords;
// Allow keywords in function body (we'd have a different statement if we were deeper)
case FunctionDefinition fd when index >= fd.HeaderIndex:
return CompletionListOptions.AllKeywords;
// Allow keywords within with blocks, but not in their definition
case WithStatement ws:
return index >= ws.HeaderIndex || index <= ws.KeywordEndIndex
? CompletionListOptions.AllKeywords : CompletionListOptions.ExpressionKeywords;
default:
return CompletionListOptions.ExpressionKeywords;
}
}