in src/Trinity.VSExtension/TrinityVSExtension/EditorExtension/AutoCompletion/CompletionSource.cs [194:299]
private TSLCompletionState GetCompletionState(ICompletionSession session)
{
/* We decide to parse the current line in this routine,
* since it will provide real-time token information
* without which we would have to depend on the lagging
* and unnecessary global parse results.
*/
var caretSnapshotPoint = session.TextView.Caret.Position.BufferPosition;
var tokenSpans = parser.ParseTokens(textBuffer.CurrentSnapshot.GetLineFromPosition(caretSnapshotPoint.Position).Extent);
var syntaxSpanTypes = parser.GetSyntaxSpanTypes(caretSnapshotPoint);
bool afterTypes = false;
bool beforeRAngle = false;
bool afterLAngle = false;
bool afterProtocol = false;
bool afterColon = false;
bool afterRAngle = false;
bool afterProtocolTypeSpecifier = false;
bool afterProtocolDataSpecifier = false;
bool afterTopLevelFinalBlockTypeToken = false;
/* Compare the spans in the line with current caret */
foreach (var tokenSpan in tokenSpans)
{
if (tokenSpan.span.End <= caretSnapshotPoint)
/* caret after token */
{
if (tokenSpan.token == WrappedTokenType.T_COLON)
afterColon = true;
if (TSLSyntaxDefinition.isTypeToken(tokenSpan.token))
afterTypes = true;
if (tokenSpan.token == WrappedTokenType.T_TYPE)
afterProtocolTypeSpecifier = true;
if (tokenSpan.token == WrappedTokenType.T_REQUEST || tokenSpan.token == WrappedTokenType.T_RESPONSE)
afterProtocolDataSpecifier = true;
if (tokenSpan.token == WrappedTokenType.T_LANGLE)
afterLAngle = true;
if (tokenSpan.token == WrappedTokenType.T_PROTOCOL)
afterProtocol = true;
if (tokenSpan.token == WrappedTokenType.T_RANGLE)
afterRAngle = true;
if (TSLSyntaxDefinition.isTopLevelFinalBlockTypeToken(tokenSpan.token))
afterTopLevelFinalBlockTypeToken = true;
}
else if (tokenSpan.span.Start >= caretSnapshotPoint)
{
/* caret before token */
switch (tokenSpan.token)
{
case WrappedTokenType.T_RANGLE:
beforeRAngle = true;
break;
}
}
}
/* Note that GetSyntaxSpanTypes might return multiple results,
* so we define matching priorities here.
* For example, Comments take the highest priority to capture State so that any completion will be
* disabled.
*/
if (syntaxSpanTypes.Contains(TSLSyntaxSpanType.AttributeSet))
return TSLCompletionState.InAttributeSet;
else if (syntaxSpanTypes.Contains(TSLSyntaxSpanType.Comments))
return TSLCompletionState.InComment;
if (syntaxSpanTypes.Count != 0)
switch (syntaxSpanTypes.First())
{
case TSLSyntaxSpanType.EnumBlock:
return TSLCompletionState.InEnum;
case TSLSyntaxSpanType.IncludeBlock:
return TSLCompletionState.InInclude;
case TSLSyntaxSpanType.ProtocolBlock:
if (afterProtocolTypeSpecifier && afterColon)
return TSLCompletionState.InProtocol_SpecifyProtocolType;
else if (afterProtocolDataSpecifier && afterColon)
return TSLCompletionState.InProtocol_SpecifyProtocolData;
else
return TSLCompletionState.InProtocol_Default;
case TSLSyntaxSpanType.ProtocolGroupBlock:
if (afterProtocol)
return TSLCompletionState.InProtocolGroup_SpecifyProtocol;
else
return TSLCompletionState.InProtocolGroup_Default;
case TSLSyntaxSpanType.StructBlock:
if (beforeRAngle && afterLAngle)
return TSLCompletionState.InStruct_SpecifyFieldType;
else /* The outmost Type token? */ if (!afterTypes)
return TSLCompletionState.InStruct_SpecifyFieldTypeOrModifiers;
else /* No RAngle, we're in the middle */if (afterLAngle && !afterRAngle)
return TSLCompletionState.InStruct_SpecifyFieldType;
else
return TSLCompletionState.InStruct_SpecifyFieldName;
case TSLSyntaxSpanType.TrinitySettingBlock:
return TSLCompletionState.InTrinitySetting;
}
/* Nothing matched. we say that it's in the top-level. */
if (afterTopLevelFinalBlockTypeToken)
return TSLCompletionState.TSL_SpecifyIdentifier;
return TSLCompletionState.TSL_Default;
}