in Arriba/Arriba/Model/Query/QueryIntelliSense.cs [272:370]
public IntelliSenseResult GetIntelliSenseItems(string queryBeforeCursor, IReadOnlyCollection<Table> targetTables)
{
IntelliSenseResult result = new IntelliSenseResult() { Query = queryBeforeCursor, Incomplete = "", Complete = "", SyntaxHint = "", CompletionCharacters = new char[0], Suggestions = new List<IntelliSenseItem>() };
// If no tables were passed, show no IntelliSense (hint that there's an error blocking all tables)
if (queryBeforeCursor == null || targetTables == null || targetTables.Count == 0)
{
return result;
}
// Filter the set of tables to those valid for the query so far
targetTables = FilterToValidTablesForQuery(targetTables, queryBeforeCursor);
// If no tables remain valid, show no IntelliSense (hint that there's an error blocking all tables)
if (targetTables == null || targetTables.Count == 0)
{
return result;
}
// Get grammatical categories valid after the query prefix
TermExpression lastTerm;
IExpression query;
IntelliSenseGuidance guidance = GetCurrentTokenOptions(queryBeforeCursor, out lastTerm, out query);
bool spaceIsSafeCompletionCharacter = !String.IsNullOrEmpty(guidance.Value);
// If there are no tokens suggested here, return empty completion
if (guidance.Options == QueryTokenCategory.None)
{
return result;
}
// Compute the CurrentCompleteValue, *before* considering values, so value IntelliSense can use them
string queryWithoutIncompleteValue = queryBeforeCursor;
if (!queryWithoutIncompleteValue.EndsWith(guidance.Value)) throw new ArribaException("Error: IntelliSense suggestion couldn't be applied.");
queryWithoutIncompleteValue = queryWithoutIncompleteValue.Substring(0, queryWithoutIncompleteValue.Length - guidance.Value.Length);
// If the CurrentIncompleteValue is an explicit column name, remove and re-complete that, also
if (queryWithoutIncompleteValue.EndsWith("[")) queryWithoutIncompleteValue = queryWithoutIncompleteValue.Substring(0, queryWithoutIncompleteValue.Length - 1);
result.Complete = queryWithoutIncompleteValue;
result.Incomplete = guidance.Value;
// Build a ranked list of suggestions - preferred token categories, filtered to the prefix already typed
List<IntelliSenseItem> suggestions = new List<IntelliSenseItem>();
if (guidance.Options.HasFlag(QueryTokenCategory.BooleanOperator))
{
AddWhenPrefixes(BooleanOperators, guidance.Value, suggestions);
}
if (guidance.Options.HasFlag(QueryTokenCategory.CompareOperator))
{
AddSuggestionsForCompareOperator(targetTables, lastTerm, guidance, suggestions);
}
if (guidance.Options.HasFlag(QueryTokenCategory.ColumnName))
{
AddSuggestionsForColumnNames(targetTables, guidance, ref spaceIsSafeCompletionCharacter, suggestions);
}
// Space isn't safe to complete values (except when all explicit values shown, bool below)
if (guidance.Options.HasFlag(QueryTokenCategory.Value))
{
spaceIsSafeCompletionCharacter = false;
AddSuggestionsForTerm(targetTables, result, lastTerm, guidance, suggestions);
}
// If *only* a value is valid here, provide a syntax hint for the value type (and reconsider if space is safe to complete)
if (guidance.Options == QueryTokenCategory.Value)
{
AddSuggestionsForValue(targetTables, result, lastTerm, guidance, ref spaceIsSafeCompletionCharacter, suggestions);
}
if (guidance.Options.HasFlag(QueryTokenCategory.TermPrefixes))
{
AddWhenPrefixes(TermPrefixes, guidance.Value, suggestions);
}
// Build a list of valid completion characters
List<char> completionCharacters = new List<char>();
completionCharacters.Add('\t');
if (spaceIsSafeCompletionCharacter) completionCharacters.Add(' ');
// If column names are valid here but term prefixes or compare operators, operator start characters are valid completion characters
if (guidance.Options.HasFlag(QueryTokenCategory.ColumnName) && !guidance.Options.HasFlag(QueryTokenCategory.CompareOperator) && !guidance.Options.HasFlag(QueryTokenCategory.TermPrefixes))
{
completionCharacters.AddRange(ColumnNameCompletionCharacters);
}
// If there's only one suggestion and it's been fully typed, remove it
if (suggestions.Count == 1 && suggestions[0].Display == guidance.Value) suggestions.Clear();
// Finish populating the result
result.Suggestions = suggestions;
result.CompletionCharacters = completionCharacters;
return result;
}