public ICompletionDataList HandleKeywordCompletion (CodeCompletionContext completionContext, ExpressionResult result, int wordStart, string word)
{
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
return null;
DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset);
switch (word) {
case "using":
if (result.ExpressionContext != ExpressionContext.NamespaceNameExcepted)
return null;
return CreateCompletionData (location, new NamespaceResolveResult (""), result, null);
case "namespace":
result.ExpressionContext = ExpressionContext.NamespaceNameExcepted;
return CreateCompletionData (location, new NamespaceResolveResult (""), result, null);
case "case":
return CreateCaseCompletionData (location, result);
case ",":
case ":":
if (result.ExpressionContext == ExpressionContext.InheritableType) {
IType cls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
CompletionDataList completionList = new ProjectDomCompletionDataList ();
List<string> namespaceList = GetUsedNamespaces ();
CSharpTextEditorCompletion.CompletionDataCollector col = new CSharpTextEditorCompletion.CompletionDataCollector (dom, completionList, Document.CompilationUnit, null, location);
bool isInterface = false;
HashSet<string> baseTypeNames = new HashSet<string> ();
if (cls != null) {
baseTypeNames.Add (cls.Name);
if (cls.ClassType == ClassType.Struct)
isInterface = true;
}
int tokenIndex = completionContext.TriggerOffset;
// Search base types " : [Type1, ... ,TypeN,] <Caret>"
string token = null;
do {
token = GetPreviousToken (ref tokenIndex, false);
if (string.IsNullOrEmpty (token))
break;
token = token.Trim ();
if (Char.IsLetterOrDigit (token[0]) || token[0] == '_') {
IType baseType = dom.SearchType (Document.CompilationUnit, cls, result.Region.Start, token);
if (baseType != null) {
if (baseType.ClassType != ClassType.Interface)
isInterface = true;
baseTypeNames.Add (baseType.Name);
}
}
} while (token != ":");
foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) {
IType type = o as IType;
if (type != null && (type.IsStatic || type.IsSealed || baseTypeNames.Contains (type.Name) || isInterface && type.ClassType != ClassType.Interface)) {
continue;
}
if (o is Namespace && !namespaceList.Any (ns => ns.StartsWith (((Namespace)o).FullName)))
continue;
col.Add (o);
}
// Add inner classes
Stack<IType> innerStack = new Stack<IType> ();
innerStack.Push (cls);
while (innerStack.Count > 0) {
IType curType = innerStack.Pop ();
if (curType == null)
continue;
foreach (IType innerType in curType.InnerTypes) {
if (innerType != cls)
// don't add the calling class as possible base type
col.Add (innerType);
}
if (curType.DeclaringType != null)
innerStack.Push (curType.DeclaringType);
}
return completionList;
}
break;
case "is":
case "as":
{
CompletionDataList completionList = new ProjectDomCompletionDataList ();
ExpressionResult expressionResult = FindExpression (dom, completionContext, wordStart - textEditorData.Caret.Offset);
NRefactoryResolver resolver = CreateResolver ();
ResolveResult resolveResult = resolver.Resolve (expressionResult, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
if (resolveResult != null && resolveResult.ResolvedType != null) {
CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
IType foundType = null;
if (word == "as") {
ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForAsCompletion (textEditorData, Document.CompilationUnit, Document.FileName, resolver.CallingType);
if (exactContext is ExpressionContext.TypeExpressionContext) {
foundType = resolver.SearchType (((ExpressionContext.TypeExpressionContext)exactContext).Type);
AddAsCompletionData (col, foundType);
}
}
if (foundType == null)
foundType = resolver.SearchType (resolveResult.ResolvedType);
if (foundType != null) {
if (foundType.ClassType == ClassType.Interface)
foundType = resolver.SearchType (DomReturnType.Object);
foreach (IType type in dom.GetSubclasses (foundType)) {
if (type.IsSpecialName || type.Name.StartsWith ("<"))
continue;
AddAsCompletionData (col, type);
}
}
List<string> namespaceList = GetUsedNamespaces ();
foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) {
if (o is IType) {
IType type = (IType)o;
if (type.ClassType != ClassType.Interface || type.IsSpecialName || type.Name.StartsWith ("<"))
continue;
// if (foundType != null && !dom.GetInheritanceTree (foundType).Any (x => x.FullName == type.FullName))
// continue;
AddAsCompletionData (col, type);
continue;
}
if (o is Namespace)
continue;
col.Add (o);
}
return completionList;
}
result.ExpressionContext = ExpressionContext.TypeName;
return CreateCtrlSpaceCompletionData (completionContext, result);
}
case "override":
// Look for modifiers, in order to find the beginning of the declaration
int firstMod = wordStart;
int i = wordStart;
for (int n = 0; n < 3; n++) {
string mod = GetPreviousToken (ref i, true);
if (mod == "public" || mod == "protected" || mod == "private" || mod == "internal" || mod == "sealed") {
firstMod = i;
} else if (mod == "static") {
// static methods are not overridable
return null;
} else
break;
}
IType overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
if (overrideCls == null)
overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine - 1, 1));
if (overrideCls != null && (overrideCls.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) {
string modifiers = textEditorData.GetTextBetween (firstMod, wordStart);
return GetOverrideCompletionData (completionContext, overrideCls, modifiers);
}
return null;
case "partial":
// Look for modifiers, in order to find the beginning of the declaration
firstMod = wordStart;
i = wordStart;
for (int n = 0; n < 3; n++) {
string mod = GetPreviousToken (ref i, true);
if (mod == "public" || mod == "protected" || mod == "private" || mod == "internal" || mod == "sealed") {
firstMod = i;
} else if (mod == "static") {
// static methods are not overridable
return null;
} else
break;
}
overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
if (overrideCls != null && (overrideCls.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) {
string modifiers = textEditorData.GetTextBetween (firstMod, wordStart);
return GetPartialCompletionData (completionContext, overrideCls, modifiers);
}
return null;
case "new":
IType callingType = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (textEditorData.Caret.Line, textEditorData.Caret.Column));
ExpressionContext newExactContext = new NewCSharpExpressionFinder (dom).FindExactContextForNewCompletion (textEditorData, Document.CompilationUnit, Document.FileName, callingType);
if (newExactContext is ExpressionContext.TypeExpressionContext)
return CreateTypeCompletionData (location, callingType, newExactContext, ((ExpressionContext.TypeExpressionContext)newExactContext).Type, ((ExpressionContext.TypeExpressionContext)newExactContext).UnresolvedType);
if (newExactContext == null) {
int j = completionContext.TriggerOffset - 4;
string token = GetPreviousToken (ref j, true);
string yieldToken = GetPreviousToken (ref j, true);
if (token == "return") {
NRefactoryResolver resolver = CreateResolver ();
resolver.SetupResolver (new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
IReturnType returnType = resolver.CallingMember.ReturnType;
if (yieldToken == "yield" && returnType.GenericArguments.Count > 0)
returnType = returnType.GenericArguments[0];
if (resolver.CallingMember != null)
return CreateTypeCompletionData (location, callingType, newExactContext, null, returnType);
}
}
return CreateCtrlSpaceCompletionData (completionContext, null);
case "if":
case "elif":
if (stateTracker.Engine.IsInsidePreprocessorDirective)
return GetDefineCompletionData ();
return null;
case "yield":
CompletionDataList yieldDataList = new CompletionDataList ();
yieldDataList.DefaultCompletionString = "return";
yieldDataList.Add ("break", "md-keyword");
yieldDataList.Add ("return", "md-keyword");
return yieldDataList;
case "where":
CompletionDataList whereDataList = new CompletionDataList ();
NRefactoryResolver constraintResolver = CreateResolver ();
constraintResolver.SetupResolver (new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
if (constraintResolver.CallingMember is IMethod) {
foreach (ITypeParameter tp in ((IMethod)constraintResolver.CallingMember).TypeParameters) {
whereDataList.Add (tp.Name, "md-keyword");
}
} else {
if (constraintResolver.CallingType != null) {
foreach (ITypeParameter tp in constraintResolver.CallingType.TypeParameters) {
whereDataList.Add (tp.Name, "md-keyword");
}
}
}
return whereDataList;
}
if (IsInLinqContext (result)) {
if (linqKeywords.Contains (word)) {
if (word == "from") // after from no auto code completion.
return null;
result.Expression = "";
return CreateCtrlSpaceCompletionData (completionContext, result);
}
CompletionDataList dataList = new ProjectDomCompletionDataList ();
CompletionDataCollector col = new CompletionDataCollector (dom, dataList, Document.CompilationUnit, null, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
foreach (string kw in linqKeywords) {
col.Add (kw, "md-keyword");
}
return dataList;
}
return null;
}