176
// IDisposable timer = null;
178
if (dom == null /*|| Document.CompilationUnit == null*/)
180
if (completionChar != '#' && stateTracker.Engine.IsInsidePreprocessorDirective)
182
// timer = Counters.ResolveTime.BeginTiming ();
183
DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 1);
184
stateTracker.UpdateEngine ();
185
ExpressionResult result;
186
int cursor, newCursorOffset = 0;
187
switch (completionChar) {
190
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
192
result = FindExpression (dom, completionContext);
193
if (result == null || result.Expression == null)
195
int idx = result.Expression.LastIndexOf ('.');
197
result.Expression = result.Expression.Substring (0, idx);
198
NRefactoryResolver resolver = CreateResolver ();
199
ResolveResult resolveResult = resolver.Resolve (result, location);
200
if (resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.PrimitiveExpression) {
201
ICSharpCode.NRefactory.Ast.PrimitiveExpression pex = (ICSharpCode.NRefactory.Ast.PrimitiveExpression)resolver.ResolvedExpression;
202
if (!tryToForceCompletion && !(pex.Value is string || pex.Value is char || pex.Value is bool))
206
return CreateCompletionData (location, resolveResult, result, resolver);
208
if (stateTracker.Engine.IsInsidePreprocessorDirective)
209
return GetDirectiveCompletionData ();
212
cursor = Editor.SelectionStartPosition;
214
if (stateTracker.Engine.IsInsideDocLineComment) {
215
string lineText = Editor.GetLineText (completionContext.TriggerLine);
216
int startIndex = Math.Min (completionContext.TriggerLineOffset - 1, lineText.Length - 1);
218
while (startIndex >= 0 && lineText[startIndex] != '<') {
220
if (lineText[startIndex] == '/') { // already closed.
226
if (startIndex >= 0) {
227
int endIndex = startIndex;
228
while (endIndex <= completionContext.TriggerLineOffset && endIndex < lineText.Length && !Char.IsWhiteSpace (lineText[endIndex])) {
231
string tag = endIndex - startIndex - 1 > 0 ? lineText.Substring (startIndex + 1, endIndex - startIndex - 2) : null;
232
if (!String.IsNullOrEmpty (tag) && commentTags.IndexOf (tag) >= 0) {
233
Editor.InsertText (cursor, "</" + tag + ">");
234
Editor.CursorPosition = cursor;
194
// IDisposable timer = null;
196
if (dom == null /*|| Document.CompilationUnit == null*/)
198
if (completionChar != '#' && stateTracker.Engine.IsInsidePreprocessorDirective)
200
// timer = Counters.ResolveTime.BeginTiming ();
201
DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 1);
202
stateTracker.UpdateEngine ();
203
ExpressionResult result;
204
int cursor, newCursorOffset = 0, cpos;
206
CodeCompletionContext ctx;
207
NRefactoryParameterDataProvider provider;
210
switch (completionChar) {
213
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
215
result = FindExpression (dom, completionContext);
216
if (result == null || result.Expression == null)
218
int idx = result.Expression.LastIndexOf ('.');
220
result.Expression = result.Expression.Substring (0, idx);
221
// don't parse expressions that end with more than 1 dot - see #646820
222
if (result.Expression.EndsWith ("."))
224
NRefactoryResolver resolver = CreateResolver ();
225
ResolveResult resolveResult = resolver.Resolve (result, location);
226
if (resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.PrimitiveExpression) {
227
ICSharpCode.NRefactory.Ast.PrimitiveExpression pex = (ICSharpCode.NRefactory.Ast.PrimitiveExpression)resolver.ResolvedExpression;
228
if (!tryToForceCompletion && !(pex.Value is string || pex.Value is char || pex.Value is bool))
232
return CreateCompletionData (location, resolveResult, result, resolver);
234
if (stateTracker.Engine.IsInsidePreprocessorDirective)
235
return GetDirectiveCompletionData ();
238
cursor = textEditorData.IsSomethingSelected ? textEditorData.SelectionRange.Offset : textEditorData.Caret.Offset;
240
if (stateTracker.Engine.IsInsideDocLineComment) {
241
string lineText = textEditorData.GetLineText (completionContext.TriggerLine);
242
int startIndex = Math.Min (completionContext.TriggerLineOffset - 1, lineText.Length - 1);
244
while (startIndex >= 0 && lineText [startIndex] != '<') {
246
if (lineText [startIndex] == '/') { // already closed.
252
if (startIndex >= 0) {
253
int endIndex = startIndex;
254
while (endIndex <= completionContext.TriggerLineOffset && endIndex < lineText.Length && !Char.IsWhiteSpace (lineText [endIndex])) {
257
string tag = endIndex - startIndex - 1 > 0 ? lineText.Substring (startIndex + 1, endIndex - startIndex - 2) : null;
258
if (!String.IsNullOrEmpty (tag) && commentTags.IndexOf (tag) >= 0) {
259
textEditorData.Insert (cursor, "</" + tag + ">");
260
textEditorData.Caret.Offset = cursor;
240
266
/* Disabled because it gives problems when declaring arrays - for example string [] should not pop up code completion.
242
268
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
245
271
if (result.ExpressionContext == ExpressionContext.Attribute)
246
272
return CreateCtrlSpaceCompletionData (completionContext, result);
249
if (stateTracker.Engine.IsInsideDocLineComment)
250
return GetXmlDocumentationCompletionData ();
253
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
255
result = FindExpression (dom, completionContext, -1);
256
if (result == null || result.Expression == null)
258
resolver = CreateResolver ();
259
resolveResult = resolver.Resolve (result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 2));
261
if (resolveResult != null && resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.TypeOfExpression) {
262
CompletionDataList completionList = new ProjectDomCompletionDataList ();
264
CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
265
AddPrimitiveTypes (col);
266
foreach (object o in dom.GetNamespaceContents (GetUsedNamespaces (), true, true)) {
269
if (resolver.CallingMember is IMethod) {
270
foreach (ITypeParameter tp in ((IMethod)resolver.CallingMember).TypeParameters) {
271
col.Add (tp.Name, "md-keyword");
274
if (resolver.CallingType != null) {
275
foreach (ITypeParameter tp in resolver.CallingType.TypeParameters) {
276
col.Add (tp.Name, "md-keyword");
279
return completionList;
283
cursor = Editor.SelectionStartPosition;
275
if (stateTracker.Engine.IsInsideDocLineComment)
276
return GetXmlDocumentationCompletionData ();
279
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
281
result = FindExpression (dom, completionContext, -1);
282
if (result == null || result.Expression == null)
284
resolver = CreateResolver ();
285
resolveResult = resolver.Resolve (result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 2));
286
if (resolveResult == null)
289
if (resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.TypeOfExpression) {
290
CompletionDataList completionList = new ProjectDomCompletionDataList ();
292
CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
293
AddPrimitiveTypes (col);
294
foreach (object o in dom.GetNamespaceContents (GetUsedNamespaces (), true, true)) {
297
if (resolver.CallingMember is IMethod) {
298
foreach (ITypeParameter tp in ((IMethod)resolver.CallingMember).TypeParameters) {
299
col.Add (tp.Name, "md-keyword");
302
if (resolver.CallingType != null) {
303
foreach (ITypeParameter tp in resolver.CallingType.TypeParameters) {
304
col.Add (tp.Name, "md-keyword");
307
return completionList;
309
if (resolveResult is MethodResolveResult) {
310
var methodResolveResult = resolveResult as MethodResolveResult;
311
return CreateParameterCompletion (resolver, location, result.ExpressionContext, methodResolveResult.Methods, 0);
315
if (!GetParameterCompletionCommandOffset (out cpos))
317
ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
318
provider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
319
if (provider != null) {
320
int currentParameter = provider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1;
321
return CreateParameterCompletion (CreateResolver (), location, ExpressionContext.MethodBody, provider.Methods, currentParameter);
325
cursor = textEditorData.IsSomethingSelected ? textEditorData.SelectionRange.Offset : textEditorData.Caret.Offset;
287
if (stateTracker.Engine.IsInsideDocLineComment) {
288
string lineText = Editor.GetLineText (completionContext.TriggerLine);
289
bool startsDocComment = true;
291
for (int i = 0; i < completionContext.TriggerLineOffset && i < lineText.Length; i++) {
292
if (lineText[i] == '/') {
296
if (!Char.IsWhiteSpace (lineText[i])) {
297
startsDocComment = false;
301
// check if lines above already start a doc comment
302
for (int i = completionContext.TriggerLine - 1; i >= 0; i--) {
303
string text = Editor.GetLineText (i).Trim ();
304
if (text.Length == 0)
306
if (text.StartsWith ("///")) {
307
startsDocComment = false;
329
if (stateTracker.Engine.IsInsideDocLineComment) {
330
string lineText = textEditorData.GetLineText (completionContext.TriggerLine);
331
bool startsDocComment = true;
333
for (int i = 0; i < completionContext.TriggerLineOffset && i < lineText.Length; i++) {
334
if (lineText [i] == '/') {
338
if (!Char.IsWhiteSpace (lineText [i])) {
339
startsDocComment = false;
343
// check if lines above already start a doc comment
344
for (int i = completionContext.TriggerLine - 2; i >= 1; i--) {
345
string text = textEditorData.GetLineText (i);
346
if (text.Length == 0)
348
if (text.StartsWith ("///")) {
349
startsDocComment = false;
313
// check if following lines start a doc comment
314
for (int i = completionContext.TriggerLine + 1; i < Editor.LineCount; i++) {
315
string text = Editor.GetLineText (i);
319
if (text.Length == 0)
321
if (text.StartsWith ("///")) {
322
startsDocComment = false;
355
// check if following lines start a doc comment
356
for (int i = completionContext.TriggerLine; i <= textEditorData.Document.LineCount; i++) {
357
string text = textEditorData.GetLineText (i);
361
if (text.Length == 0)
363
if (text.StartsWith ("///")) {
364
startsDocComment = false;
328
if (!startsDocComment || slashes != 3)
330
StringBuilder generatedComment = new StringBuilder ();
331
bool generateStandardComment = true;
332
ParsedDocument currentParsedDocument = Document.UpdateParseDocument ();
333
IType insideClass = NRefactoryResolver.GetTypeAtCursor (currentParsedDocument.CompilationUnit, Document.FileName, location);
334
if (insideClass != null) {
335
string indent = GetLineWhiteSpace (lineText);
336
if (insideClass.ClassType == ClassType.Delegate) {
370
if (!startsDocComment || slashes != 3)
372
StringBuilder generatedComment = new StringBuilder ();
373
bool generateStandardComment = true;
374
ParsedDocument currentParsedDocument = Document.UpdateParseDocument ();
375
IType insideClass = NRefactoryResolver.GetTypeAtCursor (currentParsedDocument.CompilationUnit, Document.FileName, location);
376
if (insideClass != null) {
377
string indent = textEditorData.Document.GetLineIndent (completionContext.TriggerLine);
378
if (insideClass.ClassType == ClassType.Delegate) {
379
AppendSummary (generatedComment, indent, out newCursorOffset);
381
foreach (IMethod method in insideClass.Methods)
383
AppendMethodComment (generatedComment, indent, m);
384
generateStandardComment = false;
386
if (!IsInsideClassBody (insideClass, completionContext.TriggerLine, completionContext.TriggerLineOffset))
388
string body = GenerateBody (insideClass, completionContext.TriggerLine, indent, out newCursorOffset);
389
if (!String.IsNullOrEmpty (body)) {
390
generatedComment.Append (body);
391
generateStandardComment = false;
395
if (generateStandardComment) {
396
string indent = textEditorData.Document.GetLineIndent (completionContext.TriggerLine);
337
397
AppendSummary (generatedComment, indent, out newCursorOffset);
339
foreach (IMethod method in insideClass.Methods)
341
AppendMethodComment (generatedComment, indent, m);
342
generateStandardComment = false;
344
if (!IsInsideClassBody (insideClass, completionContext.TriggerLine, completionContext.TriggerLineOffset))
346
string body = GenerateBody (insideClass, completionContext.TriggerLine, indent, out newCursorOffset);
347
if (!String.IsNullOrEmpty (body)) {
348
generatedComment.Append (body);
349
generateStandardComment = false;
353
if (generateStandardComment) {
354
string indent = GetLineWhiteSpace (Editor.GetLineText (completionContext.TriggerLine));
355
AppendSummary (generatedComment, indent, out newCursorOffset);
357
Editor.EndAtomicUndo ();
358
Editor.BeginAtomicUndo ();
359
Editor.InsertText (cursor, generatedComment.ToString ());
360
Editor.CursorPosition = cursor + newCursorOffset;
399
textEditorData.Document.EndAtomicUndo ();
400
textEditorData.Document.BeginAtomicUndo ();
401
textEditorData.Insert (cursor, generatedComment.ToString ());
402
textEditorData.Caret.Offset = cursor + newCursorOffset;
366
408
// if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
382
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
384
result = FindExpression (dom, completionContext);
389
int tokenIndex = completionContext.TriggerOffset;
390
string token = GetPreviousToken (ref tokenIndex, false);
391
if (result.ExpressionContext == ExpressionContext.ObjectInitializer) {
392
resolver = CreateResolver ();
393
ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (Editor, resolver.Unit, Document.FileName, resolver.CallingType);
394
IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType;
395
if (objectInitializer != null && objectInitializer.ArrayDimensions == 0 && objectInitializer.PointerNestingLevel == 0 && (token == "{" || token == ","))
396
return CreateCtrlSpaceCompletionData (completionContext, result);
400
string prevToken = GetPreviousToken (ref j, false);
401
if (prevToken == "=" || prevToken == "+" || prevToken == "-") {
402
token = prevToken + token;
409
result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset - 1);
410
resolver = CreateResolver ();
411
resolveResult = resolver.Resolve (result, location);
412
if (resolveResult != null) {
413
IType resolvedType = dom.GetType (resolveResult.ResolvedType);
414
if (resolvedType == null)
416
if (resolvedType.ClassType == ClassType.Enum) {
417
CompletionDataList completionList = new ProjectDomCompletionDataList ();
418
CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
419
IReturnType returnType = new DomReturnType (resolvedType);
421
foreach (IUsing u in Document.CompilationUnit.Usings) {
422
foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) {
423
if (alias.Value.ToInvariantString () == returnType.ToInvariantString ()) {
424
cdc.Add (alias.Key, "md-class");
424
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
426
result = FindExpression (dom, completionContext);
430
int tokenIndex = completionContext.TriggerOffset;
431
string token = GetPreviousToken (ref tokenIndex, false);
432
if (result.ExpressionContext == ExpressionContext.ObjectInitializer) {
433
resolver = CreateResolver ();
434
ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (textEditorData, resolver.Unit, Document.FileName, resolver.CallingType);
435
IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType;
436
if (objectInitializer != null && objectInitializer.ArrayDimensions == 0 && objectInitializer.PointerNestingLevel == 0 && (token == "{" || token == ","))
437
return CreateCtrlSpaceCompletionData (completionContext, result);
441
string prevToken = GetPreviousToken (ref j, false);
442
if (prevToken == "=" || prevToken == "+" || prevToken == "-") {
443
token = prevToken + token;
450
if (!GetParameterCompletionCommandOffset (out cpos))
452
ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
453
provider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
454
if (provider != null) {
455
int currentParameter = provider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1;
456
return CreateParameterCompletion (CreateResolver (), location, ExpressionContext.IdentifierExpected, provider.Methods, currentParameter);
461
result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset - 1);
462
resolver = CreateResolver ();
463
resolveResult = resolver.Resolve (result, location);
464
if (resolveResult != null) {
465
resolvedType = dom.GetType (resolveResult.ResolvedType);
466
if (resolvedType == null)
468
if (resolvedType.ClassType == ClassType.Enum) {
469
CompletionDataList completionList = new ProjectDomCompletionDataList ();
470
CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
471
IReturnType returnType = new DomReturnType (resolvedType);
473
foreach (IUsing u in Document.CompilationUnit.Usings) {
474
foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) {
475
if (alias.Value.ToInvariantString () == returnType.ToInvariantString ()) {
476
cdc.Add (alias.Key, "md-class");
430
cdc.Add (returnType);
481
if (!added && !string.IsNullOrEmpty (returnType.Namespace))
482
cdc.Add (returnType);/*
431
483
foreach (object o in CreateCtrlSpaceCompletionData (completionContext, result)) {
432
484
MemberCompletionData memberData = o as MemberCompletionData;
433
if (memberData == null || memberData.Member == null)
485
if (memberData == null || memberData.Member == null) {
486
completionList.Add (o as CompletionData);
435
489
if (memberData.Member is IMember) {
436
490
returnType = ((IMember)memberData.Member).ReturnType;
437
491
} else if (memberData.Member is IParameter) {
464
524
returnType = ((LocalVariable)memberData.Member).ReturnType;
466
if (returnType != null && returnType.FullName == DomReturnType.Bool.FullName)
526
// filter out void types
527
if (returnType != null && returnType.FullName != DomReturnType.Void.FullName)
467
528
completionList.Add (memberData);
530
resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc);
531
return completionList;
533
if (resolvedType.ClassType == ClassType.Delegate && token == "=") {
534
CompletionDataList completionList = new ProjectDomCompletionDataList ();
535
string parameterDefinition = AddDelegateHandlers (completionList, resolvedType);
536
string varName = GetPreviousMemberReferenceExpression (tokenIndex);
537
completionList.Add (new EventCreationCompletionData (textEditorData, varName, resolvedType, null, parameterDefinition, resolver.CallingMember, resolvedType));
538
return completionList;
544
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
546
result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset);
547
resolver = CreateResolver ();
548
resolveResult = resolver.Resolve (result, location);
550
if (resolveResult is MemberResolveResult) {
551
MemberResolveResult mrr = resolveResult as MemberResolveResult;
552
IEvent evt = mrr.ResolvedMember as IEvent;
555
IType delegateType = resolver.SearchType (evt.ReturnType);
556
if (delegateType == null || delegateType.ClassType != ClassType.Delegate)
558
CompletionDataList completionList = new ProjectDomCompletionDataList ();
559
CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
561
IType declaringType = resolver.CallingType;
562
if (Document.LastErrorFreeParsedDocument != null) {
563
declaringType = Document.LastErrorFreeParsedDocument.CompilationUnit.GetType (declaringType.FullName, declaringType.TypeParameters.Count);
565
IType typeFromDatabase = null;
566
if (declaringType != null) {
567
typeFromDatabase = dom.GetType (declaringType.FullName, new DomReturnType (declaringType).GenericArguments) ?? declaringType;
568
bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType);
569
foreach (IType type in dom.GetInheritanceTree (typeFromDatabase)) {
570
foreach (IMethod method in type.Methods) {
571
if (method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) && MatchDelegate (delegateType, method)) {
572
CompletionData data = cdc.Add (method);
573
data.SetText (data.CompletionText + ";");
579
string parameterDefinition = AddDelegateHandlers (completionList, delegateType);
580
string varName = GetPreviousMemberReferenceExpression (tokenIndex);
581
completionList.Add (new EventCreationCompletionData (textEditorData, varName, delegateType, evt, parameterDefinition, resolver.CallingMember, typeFromDatabase));
469
584
return completionList;
475
if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
477
result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset);
478
resolver = CreateResolver ();
479
resolveResult = resolver.Resolve (result, location);
481
if (resolveResult is MemberResolveResult) {
482
MemberResolveResult mrr = resolveResult as MemberResolveResult;
483
IEvent evt = mrr.ResolvedMember as IEvent;
486
IType delegateType = resolver.SearchType (evt.ReturnType);
487
if (delegateType == null || delegateType.ClassType != ClassType.Delegate)
489
CompletionDataList completionList = new ProjectDomCompletionDataList ();
490
CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
492
IType declaringType = resolver.CallingType;
493
if (Document.LastErrorFreeParsedDocument != null) {
494
declaringType = Document.LastErrorFreeParsedDocument.CompilationUnit.GetType (declaringType.FullName, declaringType.TypeParameters.Count);
496
IType typeFromDatabase = dom.GetType (declaringType.FullName, new DomReturnType (declaringType).GenericArguments) ?? declaringType;
497
bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType);
498
foreach (IType type in dom.GetInheritanceTree (typeFromDatabase)) {
499
foreach (IMethod method in type.Methods) {
500
if (method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) && MatchDelegate (delegateType, method)) {
501
CompletionData data = cdc.Add (method);
502
data.SetText (data.CompletionText + ";");
507
IMethod delegateMethod = delegateType.Methods.First ();
508
completionList.Add ("delegate", "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate {\n" + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|\n" + stateTracker.Engine.ThisLineIndent +"};");
509
StringBuilder sb = new StringBuilder ("(");
510
for (int k = 0; k < delegateMethod.Parameters.Count; k++) {
513
IType parameterType = dom.GetType (delegateMethod.Parameters[k].ReturnType);
514
IReturnType returnType = parameterType != null ? new DomReturnType (parameterType) : delegateMethod.Parameters[k].ReturnType;
515
sb.Append (CompletionDataCollector.ambience.GetString (Document.CompilationUnit.ShortenTypeName (returnType, Document.TextEditor.CursorLine, Document.TextEditor.CursorColumn), OutputFlags.ClassBrowserEntries | OutputFlags.UseFullName | OutputFlags.UseFullInnerTypeName));
517
sb.Append (delegateMethod.Parameters[k].Name);
520
completionList.Add ("delegate" + sb, "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate" + sb + " {\n" + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|\n" + stateTracker.Engine.ThisLineIndent +"};");
521
string varName = GetPreviousToken (ref tokenIndex, false);
522
varName = GetPreviousToken (ref tokenIndex, false);
523
if (varName != ".") {
588
return HandleKeywordCompletion (completionContext, result, tokenIndex, token);
590
if ((Char.IsLetter (completionChar) || completionChar == '_') && TextEditorProperties.EnableAutoCodeCompletion && !stateTracker.Engine.IsInsideDocLineComment && !stateTracker.Engine.IsInsideOrdinaryCommentOrString) {
591
char prevCh = completionContext.TriggerOffset > 2 ? textEditorData.GetCharAt (completionContext.TriggerOffset - 2) : '\0';
592
char nextCh = completionContext.TriggerOffset < textEditorData.Length ? textEditorData.GetCharAt (completionContext.TriggerOffset) : ' ';
593
const string allowedChars = ";,[(){}+-*/%^?:&|~!<>=";
594
if (!Char.IsWhiteSpace (nextCh) && allowedChars.IndexOf (nextCh) < 0)
596
if (Char.IsWhiteSpace (prevCh) || allowedChars.IndexOf (prevCh) >= 0) {
597
result = FindExpression (dom, completionContext, -1);
600
if (IsInLinqContext (result)) {
601
tokenIndex = completionContext.TriggerOffset;
602
token = GetPreviousToken (ref tokenIndex, false); // token last typed
603
token = GetPreviousToken (ref tokenIndex, false); // possible linq keyword ?
604
triggerWordLength = 1;
606
if (linqKeywords.Contains (token)) {
607
if (token == "from") // after from no auto code completion.
609
result.Expression = "";
610
return CreateCtrlSpaceCompletionData (completionContext, result);
612
CompletionDataList dataList = new ProjectDomCompletionDataList ();
613
CompletionDataCollector col = new CompletionDataCollector (dom, dataList, Document.CompilationUnit, null, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
614
foreach (string kw in linqKeywords) {
615
col.Add (kw, "md-keyword");
618
} else if (result.ExpressionContext != ExpressionContext.IdentifierExpected) {
619
triggerWordLength = 1;
620
bool autoSelect = true;
621
IType returnType = null;
622
if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) {
623
ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
624
NRefactoryParameterDataProvider dataProvider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
625
if (dataProvider != null) {
626
int i = dataProvider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1;
627
foreach (var method in dataProvider.Methods) {
628
if (i < method.Parameters.Count) {
629
returnType = dom.GetType (method.Parameters [i].ReturnType);
630
autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate;
636
// Bug 677531 - Auto-complete doesn't always highlight generic parameter in method signature
637
//if (result.ExpressionContext == ExpressionContext.TypeName)
638
// autoSelect = false;
639
CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result);
640
AddEnumMembers (dataList, returnType);
641
dataList.AutoSelect = autoSelect;
526
List<string> names = new List<string> ();
527
while (varName == ".") {
528
varName = GetPreviousToken (ref tokenIndex, false);
529
if (varName == "this") {
530
names.Add ("handle");
531
} else if (varName != null) {
532
string trimmedName = varName.Trim ();
533
if (trimmedName.Length == 0)
535
names.Insert (0, trimmedName);
537
varName = GetPreviousToken (ref tokenIndex, false);
539
varName = String.Join ("", names.ToArray ());
540
foreach (char ch in varName) {
541
if (!char.IsLetterOrDigit (ch) && ch != '_') {
644
result = FindExpression (dom, completionContext, 0);
645
tokenIndex = completionContext.TriggerOffset;
548
completionList.Add (new EventCreationCompletionData (textEditorData, varName, delegateType, evt, sb.ToString (), resolver.CallingMember, typeFromDatabase));
550
return completionList;
554
return HandleKeywordCompletion (completionContext, result, tokenIndex, token);
556
if ((Char.IsLetter (completionChar) || completionChar == '_') && TextEditorProperties.EnableAutoCodeCompletion
557
&& !stateTracker.Engine.IsInsideDocLineComment
558
&& !stateTracker.Engine.IsInsideOrdinaryCommentOrString)
560
char prevCh = completionContext.TriggerOffset > 2
561
? Editor.GetCharAt (completionContext.TriggerOffset - 2)
564
char nextCh = completionContext.TriggerOffset < Editor.TextLength
565
? Editor.GetCharAt (completionContext.TriggerOffset)
567
const string allowedChars = ";,[(){}+-*/%^?:&|~!<>=";
568
if (!Char.IsWhiteSpace (nextCh) && allowedChars.IndexOf (nextCh) < 0)
570
if (Char.IsWhiteSpace (prevCh) || allowedChars.IndexOf (prevCh) >= 0)
572
result = FindExpression (dom, completionContext, -1);
575
if (IsInLinqContext (result)) {
576
tokenIndex = completionContext.TriggerOffset;
577
token = GetPreviousToken (ref tokenIndex, false); // token last typed
578
token = GetPreviousToken (ref tokenIndex, false); // possible linq keyword ?
579
triggerWordLength = 1;
581
if (linqKeywords.Contains (token)) {
582
if (token == "from") // after from no auto code completion.
647
// check foreach case, unfortunately the expression finder is too dumb to handle full type names
648
// should be overworked if the expression finder is replaced with a mcs ast based analyzer.
649
var possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // starting letter
650
possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varname
652
// read return types to '(' token
653
possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varType
654
if (possibleForeachToken == ">") {
655
while (possibleForeachToken != null && possibleForeachToken != "(") {
656
possibleForeachToken = GetPreviousToken (ref tokenIndex, false);
659
possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // (
660
if (possibleForeachToken == ".")
661
while (possibleForeachToken != null && possibleForeachToken != "(")
662
possibleForeachToken = GetPreviousToken (ref tokenIndex, false);
664
possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // foreach
666
if (possibleForeachToken == "foreach") {
667
result.ExpressionContext = ExpressionContext.ForeachInToken;
670
// result.ExpressionContext = ExpressionContext.IdentifierExpected;
584
672
result.Expression = "";
673
result.Region = DomRegion.Empty;
675
// identifier has already started with the first letter
676
completionContext.TriggerOffset--;
677
completionContext.TriggerLineOffset--;
678
completionContext.TriggerWordLength = 1;
585
679
return CreateCtrlSpaceCompletionData (completionContext, result);
587
CompletionDataList dataList = new ProjectDomCompletionDataList ();
588
CompletionDataCollector col = new CompletionDataCollector (dom, dataList, Document.CompilationUnit, null, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
589
foreach (string kw in linqKeywords) {
590
col.Add (kw, "md-keyword");
593
} else if (result.ExpressionContext != ExpressionContext.IdentifierExpected) {
594
triggerWordLength = 1;
595
bool autoSelect = true;
597
if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) {
598
CodeCompletionContext ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
599
NRefactoryParameterDataProvider provider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
600
if (provider != null) {
601
int i = provider.GetCurrentParameterIndex (ctx) - 1;
602
if (i < provider.Methods[0].Parameters.Count) {
603
IType returnType = dom.GetType (provider.Methods[0].Parameters[i].ReturnType);
604
autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate;
608
if (result.ExpressionContext == ExpressionContext.TypeName)
610
CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result);
611
dataList.AutoSelect = autoSelect;
618
685
} catch (Exception e) {
619
System.Console.WriteLine("cce: " +e);
686
LoggingService.LogError ("Unexpected code completion exception." + Environment.NewLine +
687
"FileName: " + Document.FileName + Environment.NewLine +
688
"Position: line=" + completionContext.TriggerLine + " col=" + completionContext.TriggerLineOffset + Environment.NewLine +
689
"Line text: " + Document.Editor.GetLineText (completionContext.TriggerLine),
621
// if (timer != null)
692
// if (timer != null)
698
public string GetPreviousMemberReferenceExpression (int tokenIndex)
700
string result = GetPreviousToken (ref tokenIndex, false);
701
result = GetPreviousToken (ref tokenIndex, false);
705
List<string > names = new List<string> ();
706
while (result == ".") {
707
result = GetPreviousToken (ref tokenIndex, false);
708
if (result == "this") {
709
names.Add ("handle");
710
} else if (result != null) {
711
string trimmedName = result.Trim ();
712
if (trimmedName.Length == 0)
714
names.Insert (0, trimmedName);
716
result = GetPreviousToken (ref tokenIndex, false);
718
result = String.Join ("", names.ToArray ());
719
foreach (char ch in result) {
720
if (!char.IsLetterOrDigit (ch) && ch != '_') {
729
string AddDelegateHandlers (CompletionDataList completionList, IType delegateType, bool addSemicolon = true, bool addDefault = true)
731
IMethod delegateMethod = delegateType.Methods.First ();
732
string delegateEndString = Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + "}" + (addSemicolon ? ";" : "");
733
bool containsDelegateData = completionList.Any (d => d.DisplayText.StartsWith ("delegate("));
735
completionList.Add ("delegate", "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate {" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|" + delegateEndString);
737
StringBuilder sb = new StringBuilder ("(");
738
StringBuilder sbWithoutTypes = new StringBuilder ("(");
739
for (int k = 0; k < delegateMethod.Parameters.Count; k++) {
742
sbWithoutTypes.Append (", ");
744
IType parameterType = dom.GetType (delegateMethod.Parameters [k].ReturnType);
745
IReturnType returnType = parameterType != null ? new DomReturnType (parameterType) : delegateMethod.Parameters [k].ReturnType;
746
sb.Append (CompletionDataCollector.ambience.GetString (Document.CompilationUnit.ShortenTypeName (returnType, textEditorData.Caret.Line, textEditorData.Caret.Column), OutputFlags.ClassBrowserEntries | OutputFlags.UseFullName | OutputFlags.UseFullInnerTypeName));
748
sb.Append (delegateMethod.Parameters [k].Name);
749
sbWithoutTypes.Append (delegateMethod.Parameters [k].Name);
752
sbWithoutTypes.Append (")");
753
completionList.Add ("delegate" + sb, "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate" + sb + " {" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|" + delegateEndString);
754
completionList.Add (sbWithoutTypes.ToString (), "md-keyword", GettextCatalog.GetString ("Creates lambda expression."), sbWithoutTypes + " => |" + (addSemicolon ? ";" : ""));
756
// It's needed to temporarly disable inserting auto matching bracket because the anonymous delegates are selectable with '('
757
// otherwise we would end up with () => )
758
if (!containsDelegateData) {
759
var savedValue = MonoDevelop.SourceEditor.DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket;
760
MonoDevelop.SourceEditor.DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket = false;
761
completionList.CompletionListClosed += delegate {
762
MonoDevelop.SourceEditor.DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket = savedValue;
765
return sb.ToString ();
768
public void AddEnumMembers (CompletionDataList completionList, IType resolvedType)
770
if (resolvedType == null || resolvedType.ClassType != ClassType.Enum)
772
string typeString = Document.CompilationUnit.ShortenTypeName (new DomReturnType (resolvedType), new DomLocation (Document.Editor.Caret.Line, Document.Editor.Caret.Column)).ToInvariantString ();
773
if (typeString.Contains ("."))
774
completionList.Add (typeString, resolvedType.StockIcon);
775
foreach (var field in resolvedType.Fields) {
776
if (field.IsConst || field.IsStatic)
777
completionList.Add (typeString + "." + field.Name, field.StockIcon);
779
completionList.DefaultCompletionString = typeString;
782
public CompletionDataList CreateParameterCompletion (NRefactoryResolver resolver, DomLocation location, ExpressionContext context, IEnumerable<IMethod> possibleMethods, int parameter)
784
CompletionDataList completionList = new ProjectDomCompletionDataList ();
785
var addedEnums = new HashSet<string> ();
786
var addedDelegates = new HashSet<string> ();
787
IType resolvedType = null;
788
foreach (var method in possibleMethods) {
789
if (method.Parameters.Count <= parameter)
791
resolvedType = dom.GetType (method.Parameters [parameter].ReturnType);
792
if (resolvedType == null)
794
switch (resolvedType.ClassType) {
796
if (addedEnums.Contains (resolvedType.DecoratedFullName))
798
addedEnums.Add (resolvedType.DecoratedFullName);
799
AddEnumMembers (completionList, resolvedType);
801
case ClassType.Delegate:
802
if (addedDelegates.Contains (resolvedType.DecoratedFullName))
804
addedDelegates.Add (resolvedType.DecoratedFullName);
805
string parameterDefinition = AddDelegateHandlers (completionList, resolvedType, false, addedDelegates.Count == 1);
806
string varName = "Handle" + method.Parameters [parameter].ReturnType.Name + method.Parameters [parameter].Name;
807
completionList.Add (new EventCreationCompletionData (textEditorData, varName, resolvedType, null, parameterDefinition, resolver.Unit.GetMemberAt (location), resolvedType) { AddSemicolon = false });
811
if (addedEnums.Count + addedDelegates.Count == 0)
813
CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
814
completionList.AutoCompleteEmptyMatch = false;
815
completionList.AutoSelect = false;
816
resolver.AddAccessibleCodeCompletionData (context, cdc);
817
return completionList;
627
820
public bool IsInLinqContext (ExpressionResult result)
2343
#region IPathedDocument implementation
2344
public event EventHandler<DocumentPathChangedEventArgs> PathChanged;
2346
protected virtual void OnPathChanged (DocumentPathChangedEventArgs e)
2348
EventHandler<DocumentPathChangedEventArgs> handler = this.PathChanged;
2349
if (handler != null)
2353
public class DataProvider : DropDownBoxListWindow.IListDataProvider
2357
List<IMember> memberList = new List<IMember> ();
2364
public DataProvider (Document doc, object tag, Ambience amb)
2366
this.Document = doc;
2367
this.tag = ((INode)tag).Parent;
2372
#region IListDataProvider implementation
2373
public void Reset ()
2375
memberList.Clear ();
2376
if (tag is ICompilationUnit) {
2377
Stack<IType> types = new Stack<IType> (((ICompilationUnit)tag).Types);
2378
while (types.Count > 0) {
2379
IType type = types.Pop ();
2380
memberList.Add (type);
2381
foreach (IType innerType in type.InnerTypes)
2382
types.Push (innerType);
2384
} else if (tag is IType) {
2385
memberList.AddRange (((IType)tag).Members);
2387
memberList.Sort ((x, y) => String.Compare (GetString (amb, x), GetString (amb, y), StringComparison.OrdinalIgnoreCase));
2390
string GetString (Ambience amb, IMember x)
2392
if (tag is ICompilationUnit)
2393
return amb.GetString (x, OutputFlags.IncludeGenerics | OutputFlags.IncludeParameters | OutputFlags.UseFullInnerTypeName | OutputFlags.ReformatDelegates);
2394
return amb.GetString (x, OutputFlags.IncludeGenerics | OutputFlags.IncludeParameters | OutputFlags.ReformatDelegates);
2397
public string GetText (int n)
2399
return GetString (amb, memberList[n]);
2402
public Gdk.Pixbuf GetIcon (int n)
2404
return ImageService.GetPixbuf (memberList[n].StockIcon, IconSize.Menu);
2407
public object GetTag (int n)
2409
return memberList[n];
2412
public void ActivateItem (int n)
2414
var member = memberList[n];
2415
MonoDevelop.Ide.Gui.Content.IExtensibleTextEditor extEditor = Document.GetContent<MonoDevelop.Ide.Gui.Content.IExtensibleTextEditor> ();
2416
if (extEditor != null)
2417
extEditor.SetCaretTo (Math.Max (1, member.Location.Line), member.Location.Column);
2420
public int IconCount {
2422
return memberList.Count;
2429
public class CompilationUnitDataProvider : DropDownBoxListWindow.IListDataProvider
2436
public CompilationUnitDataProvider (Document document)
2438
this.Document = document;
2441
#region IListDataProvider implementation
2442
public void Reset ()
2446
public string GetText (int n)
2448
return Document.ParsedDocument.UserRegions.ElementAt (n).Name;
2451
internal static Gdk.Pixbuf Pixbuf {
2453
return ImageService.GetPixbuf (Gtk.Stock.Add, IconSize.Menu);
2457
public Gdk.Pixbuf GetIcon (int n)
2462
public object GetTag (int n)
2464
return Document.ParsedDocument.UserRegions.ElementAt (n);
2468
public void ActivateItem (int n)
2470
var reg = Document.ParsedDocument.UserRegions.ElementAt (n);
2471
MonoDevelop.Ide.Gui.Content.IExtensibleTextEditor extEditor = Document.GetContent<MonoDevelop.Ide.Gui.Content.IExtensibleTextEditor> ();
2472
if (extEditor != null)
2473
extEditor.SetCaretTo (Math.Max (1, reg.Region.Start.Line), reg.Region.Start.Column);
2476
public int IconCount {
2478
if (Document.ParsedDocument == null)
2480
return Document.ParsedDocument.UserRegions.Count ();
2487
public Gtk.Widget CreatePathWidget (int index)
2489
PathEntry[] path = CurrentPath;
2490
if (path == null || index < 0 || index >= path.Length)
2492
var tag = path[index].Tag;
2493
DropDownBoxListWindow window = new DropDownBoxListWindow (tag is ICompilationUnit ? (DropDownBoxListWindow.IListDataProvider)new CompilationUnitDataProvider (Document) : new DataProvider (Document, tag, GetAmbience ()));
2494
window.SelectItem (path[index].Tag);
2498
public PathEntry[] CurrentPath {
2503
class CustomNode : MonoDevelop.Projects.Dom.AbstractNode
2505
public CustomNode (INode parent)
2507
this.Parent = parent;
2511
void UpdatePath (object sender, Mono.TextEditor.DocumentLocationEventArgs e)
2513
var unit = Document.CompilationUnit;
2517
var loc = textEditorData.Caret.Location;
2518
IType type = unit.GetTypeAt (loc.Line, loc.Column);
2519
IMember member = type != null && type.ClassType != ClassType.Delegate ? type.GetMemberAt (loc.Line, loc.Column) : null;
2521
List<PathEntry> result = new List<PathEntry> ();
2522
var amb = GetAmbience ();
2523
INode node = member ?? type ?? (INode)unit;
2524
while (node != null) {
2526
if (node is ICompilationUnit) {
2527
if (!Document.ParsedDocument.UserRegions.Any ())
2529
FoldingRegion reg = Document.ParsedDocument.UserRegions.Where (r => r.Region.Contains (loc.Line, loc.Column)).LastOrDefault ();
2531
entry = new PathEntry (GettextCatalog.GetString ("No region"));
2533
entry = new PathEntry (CompilationUnitDataProvider.Pixbuf,
2536
entry.Position = EntryPosition.Right;
2538
entry = new PathEntry (ImageService.GetPixbuf (((IMember)node).StockIcon, IconSize.Menu), amb.GetString ((IMember)node, OutputFlags.IncludeGenerics | OutputFlags.IncludeParameters | OutputFlags.ReformatDelegates));
2541
result.Insert (0, entry);
2544
PathEntry noSelection = null;
2546
noSelection = new PathEntry (GettextCatalog.GetString ("No selection")) { Tag = new CustomNode (Document.CompilationUnit) };
2547
} else if (member == null && type.ClassType != ClassType.Delegate)
2548
noSelection = new PathEntry (GettextCatalog.GetString ("No selection")) { Tag = new CustomNode (type) };
2549
if (noSelection != null) {
2550
/* if (result.Count > 0 && result[result.Count - 1].Tag is ICompilationUnit) {
2551
result.Insert (result.Count - 1, noSelection);
2553
result.Add (noSelection);
2556
var prev = CurrentPath;
2557
CurrentPath = result.ToArray ();
2558
OnPathChanged (new DocumentPathChangedEventArgs (prev));