diff options
Diffstat (limited to 'main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion')
24 files changed, 2600 insertions, 2426 deletions
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/AbstractParameterDataProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/AbstractParameterDataProvider.cs index d505a33737..8cde44cca3 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/AbstractParameterDataProvider.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/AbstractParameterDataProvider.cs @@ -35,7 +35,7 @@ using MonoDevelop.Ide.CodeCompletion; namespace MonoDevelop.CSharp.Completion { - abstract class AbstractParameterDataProvider : ParameterDataProvider + abstract class AbstractParameterDataProvider : ParameterHintingData { protected CSharpCompletionTextEditorExtension ext; @@ -49,28 +49,29 @@ namespace MonoDevelop.CSharp.Completion TypeSystemAstBuilder builder; protected string GetShortType (IType type) { - if (builder == null) { - var ctx = ext.CSharpUnresolvedFile.GetTypeResolveContext (ext.UnresolvedFileCompilation, ext.Document.Editor.Caret.Location); - var state = new CSharpResolver (ctx); - builder = new TypeSystemAstBuilder (state); - var dt = state.CurrentTypeDefinition; - var declaring = ctx.CurrentTypeDefinition != null ? ctx.CurrentTypeDefinition.DeclaringTypeDefinition : null; - if (declaring != null) { - while (dt != null) { - if (dt.Equals (declaring)) { - builder.AlwaysUseShortTypeNames = true; - break; - } - dt = dt.DeclaringTypeDefinition; - } - } - } - try { - return GLib.Markup.EscapeText (builder.ConvertType(type).ToString (ext.FormattingPolicy.CreateOptions ())); - } catch (Exception e) { - LoggingService.LogError ("Exception while getting short type.", e); - return ""; - } + return type.Name; +// if (builder == null) { +// var ctx = ext.CSharpUnresolvedFile.GetTypeResolveContext (ext.UnresolvedFileCompilation, ext.Document.Editor.Caret.Location); +// var state = new CSharpResolver (ctx); +// builder = new TypeSystemAstBuilder (state); +// var dt = state.CurrentTypeDefinition; +// var declaring = ctx.CurrentTypeDefinition != null ? ctx.CurrentTypeDefinition.DeclaringTypeDefinition : null; +// if (declaring != null) { +// while (dt != null) { +// if (dt.Equals (declaring)) { +// builder.AlwaysUseShortTypeNames = true; +// break; +// } +// dt = dt.DeclaringTypeDefinition; +// } +// } +// } +// try { +// return GLib.Markup.EscapeText (builder.ConvertType(type).ToString (ext.FormattingPolicy.CreateOptions ())); +// } catch (Exception e) { +// LoggingService.LogError ("Exception while getting short type.", e); +// return ""; +// } } protected string GetParameterString (IParameter parameter) diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/AnonymousMethodCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/AnonymousMethodCompletionData.cs new file mode 100644 index 0000000000..ef913a932a --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/AnonymousMethodCompletionData.cs @@ -0,0 +1,48 @@ +// +// AnonymousMethodCompletionData.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace MonoDevelop.CSharp.Completion +{ + class AnonymousMethodCompletionData : RoslynCompletionData + { + public AnonymousMethodCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler) : base (keyHandler) + { + this.Icon = "md-newmethod"; + } + + public override int CompareTo (object obj) + { + var anonymousMethodCompletionData = obj as AnonymousMethodCompletionData; + if (anonymousMethodCompletionData == null) + return -1; + + return DisplayText.CompareTo(anonymousMethodCompletionData.DisplayText); + } + + } +} + diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ArrayTypeParameterDataProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ArrayTypeParameterDataProvider.cs index f909337cbf..e41ed579e5 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ArrayTypeParameterDataProvider.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ArrayTypeParameterDataProvider.cs @@ -29,7 +29,6 @@ using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.TypeSystem; using MonoDevelop.CSharp.Formatting; using ICSharpCode.NRefactory.CSharp.TypeSystem; -using Mono.TextEditor; namespace MonoDevelop.CSharp.Completion { @@ -47,9 +46,9 @@ namespace MonoDevelop.CSharp.Completion var tooltipInfo = new TooltipInformation (); var file = ext.CSharpUnresolvedFile; var compilation = ext.UnresolvedFileCompilation; - var textEditorData = ext.TextEditorData; + var textEditorData = ext.Editor; var formattingPolicy = ext.FormattingPolicy; - var resolver = file.GetResolver (compilation, textEditorData.Caret.Location); + var resolver = file.GetResolver (compilation, textEditorData.CaretLocation); var sig = new SignatureMarkupCreator (resolver, formattingPolicy.CreateOptions ()); sig.HighlightParameter = currentParameter; tooltipInfo.SignatureMarkup = sig.GetArrayIndexerMarkup (arrayType); diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs index 6e1134678f..2374acb902 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpCompletionTextEditorExtension.cs @@ -26,45 +26,39 @@ using System; using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; using System.Collections.Generic; -using Mono.TextEditor; - using MonoDevelop.Core; using MonoDevelop.Debugger; -using MonoDevelop.Projects; using MonoDevelop.Ide.Gui; using MonoDevelop.CodeGeneration; -using MonoDevelop.Ide.TypeSystem; using MonoDevelop.Ide.Gui.Content; -using MonoDevelop.Ide.CodeTemplates; using MonoDevelop.Ide.CodeCompletion; using MonoDevelop.Components.Commands; -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.Semantics; -using ICSharpCode.NRefactory.Completion; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.CSharp.Completion; -using ICSharpCode.NRefactory.CSharp.TypeSystem; -using ICSharpCode.NRefactory.CSharp.Refactoring; - -using MonoDevelop.CSharp.Project; using MonoDevelop.CSharp.Formatting; -using MonoDevelop.CSharp.Refactoring.CodeActions; -using MonoDevelop.Refactoring; + +using ICSharpCode.NRefactory6.CSharp.Completion; +using MonoDevelop.Ide.TypeSystem; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +using MonoDevelop.Ide.Editor.Extension; +using MonoDevelop.Ide.Editor; +using System.Threading.Tasks; +using System.Threading; +using Microsoft.CodeAnalysis.CSharp; using System.Xml; +using ICSharpCode.NRefactory6.CSharp; +using MonoDevelop.Refactoring; +using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace MonoDevelop.CSharp.Completion { - public class CSharpCompletionTextEditorExtension : CompletionTextEditorExtension, IParameterCompletionDataFactory, ITextEditorMemberPositionProvider, IDebuggerExpressionResolver + sealed class CSharpCompletionTextEditorExtension : CompletionTextEditorExtension, IDebuggerExpressionResolver { - internal protected virtual Mono.TextEditor.TextEditorData TextEditorData { +/* internal protected virtual Mono.TextEditor.TextEditorData TextEditorData { get { var doc = Document; if (doc == null) @@ -76,9 +70,10 @@ namespace MonoDevelop.CSharp.Completion protected virtual IProjectContent ProjectContent { get { return Document.GetProjectContext (); } } - +*/ SyntaxTree unit; - static readonly SyntaxTree emptyUnit = new SyntaxTree (); + static readonly SyntaxTree emptyUnit = CSharpSyntaxTree.ParseText (""); + SyntaxTree Unit { get { return unit ?? emptyUnit; @@ -87,36 +82,16 @@ namespace MonoDevelop.CSharp.Completion unit = value; } } - - public new MonoDevelop.Ide.Gui.Document Document { - get { - return base.document; - } - } - public ICompilation UnresolvedFileCompilation { - get; - set; - } - - public CSharpUnresolvedFile CSharpUnresolvedFile { - get; - set; - } - public ParsedDocument ParsedDocument { get { - return document.ParsedDocument; + return DocumentContext.ParsedDocument; } } - - public virtual ICompilation Compilation { - get { return Project != null ? TypeSystemService.GetCompilation (Project) : ProjectContent.CreateCompilation (); } - } - + public MonoDevelop.Projects.Project Project { get { - return document.Project; + return DocumentContext.Project; } } @@ -125,8 +100,8 @@ namespace MonoDevelop.CSharp.Completion get { if (policy == null) { IEnumerable<string> types = MonoDevelop.Ide.DesktopService.GetMimeTypeInheritanceChain (MonoDevelop.CSharp.Formatting.CSharpFormatter.MimeType); - if (Document.Project != null && Document.Project.Policies != null) { - policy = base.Document.Project.Policies.Get<CSharpFormattingPolicy> (types); + if (DocumentContext.Project != null && DocumentContext.Project.Policies != null) { + policy = base.DocumentContext.Project.Policies.Get<CSharpFormattingPolicy> (types); } else { policy = MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<CSharpFormattingPolicy> (types); } @@ -141,12 +116,38 @@ namespace MonoDevelop.CSharp.Completion } } - internal MDRefactoringContext MDRefactoringCtx { - get; - private set; + static Func<Microsoft.CodeAnalysis.Document, CancellationToken, Task<Microsoft.CodeAnalysis.Document>> WithFrozenPartialSemanticsAsync; + static List<ICompletionData> snippets; + + static CSharpCompletionTextEditorExtension () + { + var methodInfo = typeof(Microsoft.CodeAnalysis.Document).GetMethod ("WithFrozenPartialSemanticsAsync", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod); + if (methodInfo == null) + LoggingService.LogError ("Error in completion set up: Document.WithFrozenPartialSemanticsAsync not found!"); + + WithFrozenPartialSemanticsAsync = (doc, token) => (Task<Microsoft.CodeAnalysis.Document>)methodInfo.Invoke (doc, new object[] { token }); + + + CompletionEngine.SnippetCallback = delegate(CancellationToken arg) { + if (snippets != null) + return Task.FromResult ((IEnumerable<ICompletionData>)snippets); + var newSnippets = new List<ICompletionData> (); + foreach (var ct in MonoDevelop.Ide.CodeTemplates.CodeTemplateService.GetCodeTemplates ("text/x-csharp")) { + if (string.IsNullOrEmpty (ct.Shortcut) || ct.CodeTemplateContext != MonoDevelop.Ide.CodeTemplates.CodeTemplateContext.Standard) + continue; + newSnippets.Add (new RoslynCompletionData (null) { + CompletionText = ct.Shortcut, + DisplayText = ct.Shortcut, + Description = ct.Shortcut + Environment.NewLine + GettextCatalog.GetString (ct.Description), + Icon = ct.Icon + }); + } + snippets = newSnippets; + return Task.FromResult ((IEnumerable<ICompletionData>)newSnippets); + }; + } - public CSharpCompletionTextEditorExtension () { } @@ -160,23 +161,27 @@ namespace MonoDevelop.CSharp.Completion public CSharpCompletionTextEditorExtension (MonoDevelop.Ide.Gui.Document doc, bool addEventHandlersInInitialization = true) : this () { this.addEventHandlersInInitialization = addEventHandlersInInitialization; - Initialize (doc); + Initialize (doc.Editor, doc); } - public override void Initialize () + protected override void Initialize () { base.Initialize (); - var parsedDocument = document.ParsedDocument; +// DocumentContext.DocumentParsed += HandleDocumentParsed; + additionalContextHandlers = new [] { + new ProtocolMemberContextHandler (this) + }; + + var parsedDocument = DocumentContext.ParsedDocument; if (parsedDocument != null) { - this.Unit = parsedDocument.GetAst<SyntaxTree> (); - this.UnresolvedFileCompilation = Compilation; - this.CSharpUnresolvedFile = parsedDocument.ParsedFile as CSharpUnresolvedFile; - if (addEventHandlersInInitialization) - document.Editor.Caret.PositionChanged += HandlePositionChanged; +// this.Unit = parsedDocument.GetAst<SyntaxTree> (); +// this.UnresolvedFileCompilation = DocumentContext.Compilation; +// this.CSharpUnresolvedFile = parsedDocument.ParsedFile as CSharpUnresolvedFile; +// Editor.CaretPositionChanged += HandlePositionChanged; } - + if (addEventHandlersInInitialization) - Document.DocumentParsed += HandleDocumentParsed; + DocumentContext.DocumentParsed += HandleDocumentParsed; } CancellationTokenSource src = new CancellationTokenSource (); @@ -186,46 +191,26 @@ namespace MonoDevelop.CSharp.Completion src.Cancel (); src = new CancellationTokenSource (); } - - void HandlePositionChanged (object sender, DocumentLocationEventArgs e) - { - StopPositionChangedTask (); - var doc = Document; - if (doc == null || doc.Editor == null) - return; - MDRefactoringContext.Create (doc, doc.Editor.Caret.Location, src.Token).ContinueWith (t => { - MDRefactoringCtx = t.Result; - }, TaskContinuationOptions.ExecuteSynchronously); - } - + [CommandUpdateHandler (CodeGenerationCommands.ShowCodeGenerationWindow)] public void CheckShowCodeGenerationWindow (CommandInfo info) { - info.Enabled = TextEditorData != null && Document.GetContent<ICompletionWidget> () != null; + info.Enabled = Editor != null && DocumentContext.GetContent<ICompletionWidget> () != null; } [CommandHandler (CodeGenerationCommands.ShowCodeGenerationWindow)] public void ShowCodeGenerationWindow () { - var completionWidget = Document.GetContent<ICompletionWidget> (); + var completionWidget = DocumentContext.GetContent<ICompletionWidget> (); if (completionWidget == null) return; - CodeCompletionContext completionContext = completionWidget.CreateCodeCompletionContext (TextEditorData.Caret.Offset); - GenerateCodeWindow.ShowIfValid (Document, completionContext); + CodeCompletionContext completionContext = completionWidget.CreateCodeCompletionContext (Editor.CaretOffset); + GenerateCodeWindow.ShowIfValid (Editor, DocumentContext, completionContext); } public override void Dispose () { - StopPositionChangedTask (); - unit = null; - CSharpUnresolvedFile = null; - UnresolvedFileCompilation = null; - Document.DocumentParsed -= HandleDocumentParsed; - if (unstableTypeSystemSegmentTree != null) { - unstableTypeSystemSegmentTree.RemoveListener (); - unstableTypeSystemSegmentTree = null; - } - + DocumentContext.DocumentParsed -= HandleDocumentParsed; if (validTypeSystemSegmentTree != null) { validTypeSystemSegmentTree.RemoveListener (); validTypeSystemSegmentTree = null; @@ -236,30 +221,23 @@ namespace MonoDevelop.CSharp.Completion void HandleDocumentParsed (object sender, EventArgs e) { - var newDocument = Document.ParsedDocument; - if (newDocument == null) + var parsedDocument = DocumentContext.ParsedDocument; + if (parsedDocument == null) return; - var newTree = TypeSystemSegmentTree.Create (newDocument, TextEditorData); - - if (unstableTypeSystemSegmentTree != null) - unstableTypeSystemSegmentTree.RemoveListener (); - - if (!newDocument.HasErrors) { - if (validTypeSystemSegmentTree != null) - validTypeSystemSegmentTree.RemoveListener (); - validTypeSystemSegmentTree = newTree; - unstableTypeSystemSegmentTree = null; - } else { - unstableTypeSystemSegmentTree = newTree; - } - newTree.InstallListener (document.Editor.Document); + var semanticModel = parsedDocument.GetAst<SemanticModel> (); + if (semanticModel == null) + return; + var newTree = TypeSystemSegmentTree.Create (Editor, DocumentContext, semanticModel); + + if (validTypeSystemSegmentTree != null) + validTypeSystemSegmentTree.RemoveListener (); + validTypeSystemSegmentTree = newTree; + newTree.InstallListener (Editor); - this.Unit = newDocument.GetAst<SyntaxTree> (); - this.CSharpUnresolvedFile = newDocument.ParsedFile as CSharpUnresolvedFile; - this.UnresolvedFileCompilation = Compilation; if (TypeSegmentTreeUpdated != null) TypeSegmentTreeUpdated (this, EventArgs.Empty); } + public event EventHandler TypeSegmentTreeUpdated; public void UpdateParsedDocument () @@ -267,11 +245,11 @@ namespace MonoDevelop.CSharp.Completion HandleDocumentParsed (null, null); } - public override bool KeyPress (Gdk.Key key, char keyChar, Gdk.ModifierType modifier) + public override bool KeyPress (KeyDescriptor descriptor) { - bool result = base.KeyPress (key, keyChar, modifier); + bool result = base.KeyPress (descriptor); - if (/*EnableParameterInsight &&*/ (keyChar == ',' || keyChar == ')') && CanRunParameterCompletionCommand ()) + if (/*EnableParameterInsight &&*/ (descriptor.KeyChar == ',' || descriptor.KeyChar == ')') && CanRunParameterCompletionCommand ()) base.RunParameterCompletionCommand (); // if (IsInsideComment ()) @@ -279,7 +257,7 @@ namespace MonoDevelop.CSharp.Completion return result; } - public override ICompletionDataList HandleCodeCompletion (CodeCompletionContext completionContext, char completionChar, ref int triggerWordLength) + public override Task<ICompletionDataList> HandleCodeCompletionAsync (CodeCompletionContext completionContext, char completionChar, CancellationToken token = default(CancellationToken)) { // if (!EnableCodeCompletion) // return null; @@ -288,17 +266,18 @@ namespace MonoDevelop.CSharp.Completion // var timer = Counters.ResolveTime.BeginTiming (); try { + int triggerWordLength = 0; if (char.IsLetterOrDigit (completionChar) || completionChar == '_') { - if (completionContext.TriggerOffset > 1 && char.IsLetterOrDigit (TextEditorData.GetCharAt (completionContext.TriggerOffset - 2))) + if (completionContext.TriggerOffset > 1 && char.IsLetterOrDigit (Editor.GetCharAt (completionContext.TriggerOffset - 2))) return null; triggerWordLength = 1; } - return InternalHandleCodeCompletion (completionContext, completionChar, false, ref triggerWordLength); + return InternalHandleCodeCompletion (completionContext, completionChar, false, triggerWordLength, token); } catch (Exception e) { LoggingService.LogError ("Unexpected code completion exception." + Environment.NewLine + - "FileName: " + Document.FileName + Environment.NewLine + + "FileName: " + DocumentContext.Name + Environment.NewLine + "Position: line=" + completionContext.TriggerLine + " col=" + completionContext.TriggerLineOffset + Environment.NewLine + - "Line text: " + TextEditorData.GetLineText (completionContext.TriggerLine), + "Line text: " + Editor.GetLineText (completionContext.TriggerLine), e); return null; } finally { @@ -309,10 +288,6 @@ namespace MonoDevelop.CSharp.Completion class CSharpCompletionDataList : CompletionDataList { - public CSharpResolver Resolver { - get; - set; - } } interface IListData @@ -320,120 +295,147 @@ namespace MonoDevelop.CSharp.Completion CSharpCompletionDataList List { get; set; } } - ICompletionContextProvider CreateContextProvider () - { - return new CompletionContextProvider (document.ParsedDocument, TextEditorData, validTypeSystemSegmentTree, unstableTypeSystemSegmentTree); - } - CSharpTypeResolveContext CreateTypeResolveContext () + void AddImportCompletionData (CSharpCompletionDataList result, SemanticModel semanticModel, int position, CancellationToken cancellationToken = default(CancellationToken)) { - var compilation = UnresolvedFileCompilation; - if (compilation == null) - return null; - var rctx = new CSharpTypeResolveContext (compilation.MainAssembly); - var loc = TextEditorData.Caret.Location; - rctx = rctx.WithUsingScope (CSharpUnresolvedFile.GetUsingScope (loc).Resolve (compilation)); - int offset = TextEditorData.Caret.Offset; - var curDef = GetTypeAt (offset); - if (curDef != null) { - var resolvedDef = curDef.Resolve (rctx).GetDefinition (); - if (resolvedDef == null) - return rctx; - rctx = rctx.WithCurrentTypeDefinition (resolvedDef); - var foundMember = GetMemberAt (offset); - if (foundMember != null) { - var curMember = resolvedDef.Members.FirstOrDefault (m => m.Region.FileName == foundMember.Region.FileName && m.Region.Begin == foundMember.Region.Begin); - if (curMember != null) - rctx = rctx.WithCurrentMember (curMember); + if (result.Count == 0) + return; + var root = semanticModel.SyntaxTree.GetRoot (); + var node = root.FindNode (TextSpan.FromBounds (position, position)); + var syntaxTree = root.SyntaxTree; + + if (syntaxTree.IsInNonUserCode(position, cancellationToken) || + syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken) || + syntaxTree.GetContainingTypeOrEnumDeclaration(position, cancellationToken) is EnumDeclarationSyntax || + syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) + return; + + var tokenLeftOfPosition = syntaxTree.FindTokenOnLeftOfPosition (position, cancellationToken); + + if (syntaxTree.IsGlobalStatementContext (position, cancellationToken) || + syntaxTree.IsExpressionContext (position, tokenLeftOfPosition, true, cancellationToken) || + syntaxTree.IsStatementContext (position, tokenLeftOfPosition, cancellationToken) || + syntaxTree.IsTypeContext (position, cancellationToken) || + syntaxTree.IsTypeDeclarationContext (position, tokenLeftOfPosition, cancellationToken) || + syntaxTree.IsNamespaceContext (position, cancellationToken) || + syntaxTree.IsMemberDeclarationContext (position, tokenLeftOfPosition, cancellationToken) || + syntaxTree.IsLabelContext (position, cancellationToken)) { + var usedNamespaces = new HashSet<string> (); + foreach (var un in semanticModel.GetUsingNamespacesInScope (node)) { + usedNamespaces.Add (un.GetFullName ()); } - } + var enclosingNamespaceName = semanticModel.GetEnclosingNamespace (position, cancellationToken).GetFullName (); - return rctx; + var stack = new Stack<INamespaceOrTypeSymbol>(); + foreach (var member in semanticModel.Compilation.GlobalNamespace.GetNamespaceMembers ()) + stack.Push (member); + + while (stack.Count > 0) { + if (cancellationToken.IsCancellationRequested) + break; + var current = stack.Pop(); + var currentNs = current as INamespaceSymbol; + if (currentNs != null) { + var currentNsName = currentNs.GetFullName (); + if (usedNamespaces.Contains (currentNsName) || + enclosingNamespaceName == currentNsName || + (enclosingNamespaceName.StartsWith (currentNsName) && + enclosingNamespaceName [currentNsName.Length] == '.')) { + foreach (var member in currentNs.GetNamespaceMembers ()) + stack.Push (member); + } else { + foreach (var member in currentNs.GetMembers()) + stack.Push (member); + } + } else { + var type = (INamedTypeSymbol)current; + if (type.IsImplicitClass || type.IsScriptClass) + continue; + if (type.DeclaredAccessibility != Accessibility.Public) { + if (type.DeclaredAccessibility != Accessibility.Internal) + continue; + if (!type.IsAccessibleWithin (semanticModel.Compilation.Assembly)) + continue; + } + result.Add (new ImportSymbolCompletionData (this, type, false)); + } + } + } } - CompletionEngineCache cache = new CompletionEngineCache (); - ICompletionDataList InternalHandleCodeCompletion (CodeCompletionContext completionContext, char completionChar, bool ctrlSpace, ref int triggerWordLength) + + IEnumerable<CompletionContextHandler> additionalContextHandlers; + + Task<ICompletionDataList> InternalHandleCodeCompletion (CodeCompletionContext completionContext, char completionChar, bool ctrlSpace, int triggerWordLength, CancellationToken token) { - var data = TextEditorData; - if (data.CurrentMode is TextLinkEditMode) { - if (((TextLinkEditMode)data.CurrentMode).TextLinkMode == TextLinkMode.EditIdentifier) - return null; - } - if (Unit == null || CSharpUnresolvedFile == null) - return null; - if(unstableTypeSystemSegmentTree == null && validTypeSystemSegmentTree == null) + if (Editor.EditMode != MonoDevelop.Ide.Editor.EditMode.Edit) return null; +// var data = Editor; +// if (data.CurrentMode is TextLinkEditMode) { +// if (((TextLinkEditMode)data.CurrentMode).TextLinkMode == TextLinkMode.EditIdentifier) +// return null; +// } + var offset = Editor.CaretOffset; var list = new CSharpCompletionDataList (); - list.Resolver = CSharpUnresolvedFile != null ? CSharpUnresolvedFile.GetResolver (UnresolvedFileCompilation, TextEditorData.Caret.Location) : new CSharpResolver (Compilation); - var ctx = CreateTypeResolveContext (); - if (ctx == null) - return null; - var completionDataFactory = new CompletionDataFactory (this, new CSharpResolver (ctx)); - if (MDRefactoringCtx == null) { - src.Cancel (); - MDRefactoringCtx = MDRefactoringContext.Create (Document, TextEditorData.Caret.Location).Result; - } + list.TriggerWordLength = triggerWordLength; + try { + var analysisDocument = DocumentContext.AnalysisDocument; + if (analysisDocument == null) + return null; + + var partialDoc = WithFrozenPartialSemanticsAsync (analysisDocument, token).Result; + var semanticModel = partialDoc.GetSemanticModelAsync ().Result; + + var engine = new CompletionEngine (TypeSystemService.Workspace, new RoslynCodeCompletionFactory (this, semanticModel)); + var ctx = new ICSharpCode.NRefactory6.CSharp.CompletionContext (partialDoc, offset, semanticModel); + ctx.AdditionalContextHandlers = additionalContextHandlers; + var triggerInfo = new CompletionTriggerInfo (ctrlSpace ? CompletionTriggerReason.CompletionCommand : CompletionTriggerReason.CharTyped, completionChar); + var completionResult = engine.GetCompletionDataAsync (ctx, triggerInfo, token).Result; + if (completionResult == CompletionResult.Empty) + return null; - var engine = new MonoCSharpCompletionEngine ( - this, - data.Document, - CreateContextProvider (), - completionDataFactory, - ProjectContent, - ctx - ); - completionDataFactory.Engine = engine; - engine.AutomaticallyAddImports = AddImportedItemsToCompletionList.Value; - engine.IncludeKeywordsInCompletionList = EnableAutoCodeCompletion || IncludeKeywordsInCompletionList.Value; - engine.CompletionEngineCache = cache; - if (FilterCompletionListByEditorBrowsable) { - engine.EditorBrowsableBehavior = IncludeEditorBrowsableAdvancedMembers ? EditorBrowsableBehavior.IncludeAdvanced : EditorBrowsableBehavior.Normal; - } else { - engine.EditorBrowsableBehavior = EditorBrowsableBehavior.Ignore; - } - if (Document.HasProject && MonoDevelop.Ide.IdeApp.IsInitialized) { - var configuration = Document.Project.GetConfiguration (MonoDevelop.Ide.IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration; - var par = configuration != null ? configuration.CompilationParameters as CSharpCompilerParameters : null; - if (par != null) - engine.LanguageVersion = MonoDevelop.CSharp.Parser.TypeSystemParser.ConvertLanguageVersion (par.LangVersion); - } + foreach (var symbol in completionResult) { + list.Add ((CompletionData)symbol); + } - engine.FormattingPolicy = FormattingPolicy.CreateOptions (); - engine.EolMarker = data.EolMarker; - engine.IndentString = data.Options.IndentationString; - try { - foreach (var cd in engine.GetCompletionData (completionContext.TriggerOffset, ctrlSpace)) { - list.Add (cd); - if (cd is IListData) - ((IListData)cd).List = list; + if (AddImportedItemsToCompletionList.Value && list.OfType<RoslynSymbolCompletionData> ().Any (cd => cd.Symbol is ITypeSymbol)) { + AddImportCompletionData (list, semanticModel, offset, token); } + + list.AutoCompleteEmptyMatch = completionResult.AutoCompleteEmptyMatch; + // list.AutoCompleteEmptyMatchOnCurlyBrace = completionResult.AutoCompleteEmptyMatchOnCurlyBracket; + list.AutoSelect = completionResult.AutoSelect; + list.DefaultCompletionString = completionResult.DefaultCompletionString; + // list.CloseOnSquareBrackets = completionResult.CloseOnSquareBrackets; + if (ctrlSpace) + list.AutoCompleteUniqueMatch = true; + } catch (OperationCanceledException) { + return null; + } catch (AggregateException e) { + foreach (var inner in e.Flatten ().InnerExceptions) + LoggingService.LogError ("Error while getting C# recommendations", inner); } catch (Exception e) { - LoggingService.LogError ("Error while getting completion data.", e); + LoggingService.LogError ("Error while getting C# recommendations", e); } - list.AutoCompleteEmptyMatch = engine.AutoCompleteEmptyMatch; - list.AutoCompleteEmptyMatchOnCurlyBrace = engine.AutoCompleteEmptyMatchOnCurlyBracket; - list.AutoSelect = engine.AutoSelect; - list.DefaultCompletionString = engine.DefaultCompletionString; - list.CloseOnSquareBrackets = engine.CloseOnSquareBrackets; - if (ctrlSpace) - list.AutoCompleteUniqueMatch = true; - return list.Count > 0 ? list : null; + return Task.FromResult ((ICompletionDataList)list); } public override ICompletionDataList CodeCompletionCommand (CodeCompletionContext completionContext) { int triggerWordLength = 0; - char ch = completionContext.TriggerOffset > 0 ? TextEditorData.GetCharAt (completionContext.TriggerOffset - 1) : '\0'; - return InternalHandleCodeCompletion (completionContext, ch, true, ref triggerWordLength); + char ch = completionContext.TriggerOffset > 0 ? Editor.GetCharAt (completionContext.TriggerOffset - 1) : '\0'; + return InternalHandleCodeCompletion (completionContext, ch, true, triggerWordLength, default(CancellationToken)).Result; } - static bool HasAllUsedParameters (IParameterDataProvider provider, List<string> list, int n) + static bool HasAllUsedParameters (MonoDevelop.Ide.CodeCompletion.ParameterHintingData provider, string[] list) { - int pc = provider.GetParameterCount (n); + if (provider == null || list == null) + return true; + int pc = provider.ParameterCount; foreach (var usedParam in list) { bool found = false; for (int m = 0; m < pc; m++) { - if (usedParam == provider.GetParameterName (n, m)){ + if (usedParam == provider.GetParameterName (m)){ found = true; break; } @@ -443,29 +445,24 @@ namespace MonoDevelop.CSharp.Completion } return true; } - public override int GuessBestMethodOverload (IParameterDataProvider provider, int currentOverload) + + public override int GuessBestMethodOverload (MonoDevelop.Ide.CodeCompletion.ParameterHintingResult provider, int currentOverload) { - var ctx = CreateTypeResolveContext (); - if (ctx == null) + var analysisDocument = DocumentContext.AnalysisDocument; + if (analysisDocument == null) return -1; - var engine = new CSharpParameterCompletionEngine ( - TextEditorData.Document, - CreateContextProvider (), - this, - ProjectContent, - ctx - ); - List<string> list; - int cparam = engine.GetCurrentParameterIndex (provider.StartOffset, TextEditorData.Caret.Offset, out list); - if (cparam > provider.GetParameterCount (currentOverload) && !provider.AllowParameterList (currentOverload) || !HasAllUsedParameters (provider, list, currentOverload)) { + var result = ICSharpCode.NRefactory6.CSharp.ParameterUtil.GetCurrentParameterIndex (analysisDocument, provider.StartOffset, Editor.CaretOffset).Result; + var cparam = result.ParameterIndex; + var list = result.UsedNamespaceParameters; + if (cparam > provider[currentOverload].ParameterCount && !provider[currentOverload].IsParameterListAllowed || !HasAllUsedParameters (provider[currentOverload], list)) { // Look for an overload which has more parameters int bestOverload = -1; int bestParamCount = int.MaxValue; for (int n = 0; n < provider.Count; n++) { - int pc = provider.GetParameterCount (n); + int pc = provider[n].ParameterCount; if (pc < bestParamCount && pc >= cparam) { - if (HasAllUsedParameters (provider, list, n)) { + if (HasAllUsedParameters (provider[n], list)) { bestOverload = n; bestParamCount = pc; } @@ -475,7 +472,7 @@ namespace MonoDevelop.CSharp.Completion } if (bestOverload == -1) { for (int n=0; n<provider.Count; n++) { - if (provider.AllowParameterList (n) && HasAllUsedParameters (provider, list, n)) { + if (provider[n].IsParameterListAllowed && HasAllUsedParameters (provider[n], list)) { bestOverload = n; break; } @@ -487,12 +484,12 @@ namespace MonoDevelop.CSharp.Completion } - static bool ContainsPublicConstructors (ITypeDefinition t) - { - if (t.Methods.Count (m => m.IsConstructor) == 0) - return true; - return t.Methods.Any (m => m.IsConstructor && m.IsPublic); - } +// static bool ContainsPublicConstructors (ITypeDefinition t) +// { +// if (t.Methods.Count (m => m.IsConstructor) == 0) +// return true; +// return t.Methods.Any (m => m.IsConstructor && m.IsPublic); +// } // CompletionDataList result = new ProjectDomCompletionDataList (); @@ -600,140 +597,66 @@ namespace MonoDevelop.CSharp.Completion // } // } - public override ParameterDataProvider HandleParameterCompletion (CodeCompletionContext completionContext, char completionChar) + + public override Task<MonoDevelop.Ide.CodeCompletion.ParameterHintingResult> HandleParameterCompletionAsync (CodeCompletionContext completionContext, char completionChar, CancellationToken token = default(CancellationToken)) { -// if (!EnableCodeCompletion) -// return null; - if (Unit == null || CSharpUnresolvedFile == null) + var data = Editor; + if (completionChar != '(' && completionChar != ',') return null; - var ctx = CreateTypeResolveContext (); - if (ctx == null) + if (Editor.EditMode != MonoDevelop.Ide.Editor.EditMode.Edit) return null; + var offset = Editor.CaretOffset; if (completionChar != '(' && completionChar != ',') return null; - try { - var engine = new CSharpParameterCompletionEngine ( - TextEditorData.Document, - CreateContextProvider (), - this, - ProjectContent, - ctx - ); - return engine.GetParameterDataProvider (completionContext.TriggerOffset, completionChar) as ParameterDataProvider; + + var analysisDocument = DocumentContext.AnalysisDocument; + if (analysisDocument == null) + return null; + var partialDoc = WithFrozenPartialSemanticsAsync (analysisDocument, token).Result; + var semanticModel = partialDoc.GetSemanticModelAsync ().Result; + var engine = new ParameterHintingEngine (TypeSystemService.Workspace, new RoslynParameterHintingFactory ()); + var result = engine.GetParameterDataProviderAsync (analysisDocument, semanticModel, offset, token).Result; + return Task.FromResult (new MonoDevelop.Ide.CodeCompletion.ParameterHintingResult (result.OfType<MonoDevelop.Ide.CodeCompletion.ParameterHintingData>().ToList (), result.StartOffset)); } catch (Exception e) { LoggingService.LogError ("Unexpected parameter completion exception." + Environment.NewLine + - "FileName: " + Document.FileName + Environment.NewLine + + "FileName: " + DocumentContext.Name + Environment.NewLine + "Position: line=" + completionContext.TriggerLine + " col=" + completionContext.TriggerLineOffset + Environment.NewLine + - "Line text: " + TextEditorData.GetLineText (completionContext.TriggerLine), + "Line text: " + Editor.GetLineText (completionContext.TriggerLine), e); - return null; - } finally { - // if (timer != null) - // timer.Dispose (); } + return null; } - List<string> GetUsedNamespaces () - { - var scope = CSharpUnresolvedFile.GetUsingScope (TextEditorData.Caret.Location); - var result = new List<string> (); - while (scope != null) { - result.Add (scope.NamespaceName); - var ctx = CSharpUnresolvedFile.GetResolver (Compilation, scope.Region.Begin); - foreach (var u in scope.Usings) { - var ns = u.ResolveNamespace (ctx); - if (ns == null) - continue; - result.Add (ns.FullName); - } - scope = scope.Parent; - } - return result; - } - - public override bool GetParameterCompletionCommandOffset (out int cpos) - { - var ctx = CreateTypeResolveContext (); - if (ctx == null) { - cpos = -1; - return false; - } - - var engine = new CSharpParameterCompletionEngine ( - TextEditorData.Document, - CreateContextProvider (), - this, - ProjectContent, - ctx - ); - engine.SetOffset (TextEditorData.Caret.Offset); - return engine.GetParameterCompletionCommandOffset (out cpos); - } +// List<string> GetUsedNamespaces () +// { +// var scope = CSharpUnresolvedFile.GetUsingScope (document.Editor.Caret.Location); +// var result = new List<string> (); +// while (scope != null) { +// result.Add (scope.NamespaceName); +// var ctx = CSharpUnresolvedFile.GetResolver (Document.Compilation, scope.Region.Begin); +// foreach (var u in scope.Usings) { +// var ns = u.ResolveNamespace (ctx); +// if (ns == null) +// continue; +// result.Add (ns.FullName); +// } +// scope = scope.Parent; +// } +// return result; +// } public override int GetCurrentParameterIndex (int startOffset) { - var ctx = CreateTypeResolveContext (); - if (ctx == null) + var analysisDocument = DocumentContext.AnalysisDocument; + if (analysisDocument == null) return -1; - - var engine = new CSharpParameterCompletionEngine ( - TextEditorData.Document, - CreateContextProvider (), - this, - ProjectContent, - ctx - ); - List<string> list; - return engine.GetCurrentParameterIndex (startOffset, TextEditorData.Caret.Offset, out list); + var result = ICSharpCode.NRefactory6.CSharp.ParameterUtil.GetCurrentParameterIndex (analysisDocument, startOffset, Editor.CaretOffset).Result; + return result.ParameterIndex; } - /* - internal int GetCurrentParameterIndex (ICompletionWidget widget, int offset, int memberStart) - { - int cursor = widget.CurrentCodeCompletionContext.TriggerOffset; - int i = offset; - if (i > cursor) - return -1; - if (i == cursor) - return 1; // parameters are 1 based - var types = MonoDevelop.Ide.DesktopService.GetMimeTypeInheritanceChain (CSharpFormatter.MimeType); - var engine = new CSharpIndentEngine (MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<CSharpFormattingPolicy> (types)); - int index = memberStart + 1; - int parentheses = 0; - int bracket = 0; - do { - char c = widget.GetChar (i - 1); - engine.Push (c); - switch (c) { - case '{': - if (!engine.IsInsideOrdinaryCommentOrString) - bracket++; - break; - case '}': - if (!engine.IsInsideOrdinaryCommentOrString) - bracket--; - break; - case '(': - if (!engine.IsInsideOrdinaryCommentOrString) - parentheses++; - break; - case ')': - if (!engine.IsInsideOrdinaryCommentOrString) - parentheses--; - break; - case ',': - if (!engine.IsInsideOrdinaryCommentOrString && parentheses == 1 && bracket == 0) - index++; - break; - } - i++; - } while (i <= cursor && parentheses >= 0); - - return parentheses != 1 || bracket > 0 ? -1 : index; - }*/ - +/* #region ICompletionDataFactory implementation internal class CompletionDataFactory : ICompletionDataFactory { @@ -801,12 +724,12 @@ namespace MonoDevelop.CSharp.Completion return tooltipFunc != null ? tooltipFunc (List, smartWrap) : new TooltipInformation (); } - protected List<ICompletionData> overloads; + protected List<ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData> overloads; public override bool HasOverloads { get { return overloads != null && overloads.Count > 0; } } - public override IEnumerable<ICompletionData> OverloadedData { + public override IEnumerable<ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData> OverloadedData { get { return overloads; } @@ -821,10 +744,10 @@ namespace MonoDevelop.CSharp.Completion overloads.Add (data); } - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor) { var currentWord = GetCurrentWord (window); - if (CompletionText == "new()" && keyChar == '(') { + if (CompletionText == "new()" && descriptor.KeyChar == '(') { window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, currentWord, "new"); } else { window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, currentWord, CompletionText); @@ -879,7 +802,7 @@ namespace MonoDevelop.CSharp.Completion public override TooltipInformation CreateTooltipInformation (bool smartWrap) { var def = type.GetDefinition (); - var result = def != null ? MemberCompletionData.CreateTooltipInformation (compilation, file, List.Resolver, ext.TextEditorData, ext.FormattingPolicy, def, smartWrap) : new TooltipInformation (); + var result = def != null ? MemberCompletionData.CreateTooltipInformation (compilation, file, List.Resolver, ext.Editor, ext.FormattingPolicy, def, smartWrap) : new TooltipInformation (); if (ConflictingTypes != null) { var conflicts = new StringBuilder (); var sig = new SignatureMarkupCreator (List.Resolver, ext.FormattingPolicy.CreateOptions ()); @@ -1024,11 +947,11 @@ namespace MonoDevelop.CSharp.Completion - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor) { var currentWord = GetCurrentWord (window); var text = CompletionText; - if (keyChar != '>') + if (descriptor.KeyChar != '>') text += ">"; window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, currentWord, text); } @@ -1065,7 +988,7 @@ namespace MonoDevelop.CSharp.Completion } ICompletionData ICompletionDataFactory.CreateNewPartialCompletionData (int declarationBegin, IUnresolvedTypeDefinition type, IUnresolvedMember m) { - var ctx = ext.CSharpUnresolvedFile.GetTypeResolveContext (ext.UnresolvedFileCompilation, ext.TextEditorData.Caret.Location); + var ctx = ext.CSharpUnresolvedFile.GetTypeResolveContext (ext.UnresolvedFileCompilation, ext.Editor.CaretLocation); return new NewOverrideCompletionData (ext, declarationBegin, type, m.CreateResolved (ctx)); } IEnumerable<ICompletionData> ICompletionDataFactory.CreateCodeTemplateCompletionData () @@ -1079,7 +1002,7 @@ namespace MonoDevelop.CSharp.Completion IEnumerable<ICompletionData> ICompletionDataFactory.CreatePreProcessorDefinesCompletionData () { - var project = ext.document.Project; + var project = ext.DocumentContext.Project; if (project == null) yield break; var configuration = project.GetConfiguration (MonoDevelop.Ide.IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration; @@ -1148,352 +1071,16 @@ namespace MonoDevelop.CSharp.Completion } - class ImportSymbolCompletionData : CompletionData, IEntityCompletionData - { - readonly IType type; - readonly bool useFullName; - readonly CSharpCompletionTextEditorExtension ext; - public IType Type { - get { return this.type; } - } - - public ImportSymbolCompletionData (CSharpCompletionTextEditorExtension ext, bool useFullName, IType type, bool addConstructors) - { - this.ext = ext; - this.useFullName = useFullName; - this.type = type; - this.DisplayFlags |= ICSharpCode.NRefactory.Completion.DisplayFlags.IsImportCompletion; - } - - public override TooltipInformation CreateTooltipInformation (bool smartWrap) - { - return MemberCompletionData.CreateTooltipInformation (ext, null, type.GetDefinition (), smartWrap); - } - - bool initialized = false; - bool generateUsing, insertNamespace; - - void Initialize () - { - if (initialized) - return; - initialized = true; - if (string.IsNullOrEmpty (type.Namespace)) - return; - generateUsing = !useFullName; - insertNamespace = useFullName; - } - - #region IActionCompletionData implementation - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) - { - Initialize (); - var doc = ext.document; - using (var undo = doc.Editor.OpenUndoGroup ()) { - string text = insertNamespace ? type.Namespace + "." + type.Name : type.Name; - if (text != GetCurrentWord (window)) { - if (window.WasShiftPressed && generateUsing) - text = type.Namespace + "." + text; - window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, GetCurrentWord (window), text); - } - - if (!window.WasShiftPressed && generateUsing) { - var generator = CodeGenerator.CreateGenerator (doc); - if (generator != null) { - generator.AddGlobalNamespaceImport (doc, type.Namespace); - // reparse - doc.UpdateParseDocument (); - } - } - } - ka |= KeyActions.Ignore; - } - #endregion - - #region ICompletionData implementation - public override IconId Icon { - get { - return type.GetStockIcon (); - } - } - - public override string DisplayText { - get { - return type.Name; - } - } - - static string GetDefaultDisplaySelection (string description, bool isSelected) - { - if (!isSelected) - return "<span foreground=\"darkgray\">" + description + "</span>"; - return description; - } - - string displayDescription = null; - public override string GetDisplayDescription (bool isSelected) - { - if (displayDescription == null) { - Initialize (); - if (generateUsing || insertNamespace) { - displayDescription = string.Format (GettextCatalog.GetString ("(from '{0}')"), type.Namespace); - } else { - displayDescription = ""; - } - } - return GetDefaultDisplaySelection (displayDescription, isSelected); - } - - public override string Description { - get { - return type.Namespace; - } - } - - public override string CompletionText { - get { - return type.Name; - } - } - #endregion - - - List<CompletionData> overloads; - - public override IEnumerable<ICompletionData> OverloadedData { - get { - yield return this; - if (overloads == null) - yield break; - foreach (var overload in overloads) - yield return overload; - } - } - - public override bool HasOverloads { - get { return overloads != null && overloads.Count > 0; } - } - - public override void AddOverload (ICSharpCode.NRefactory.Completion.ICompletionData data) - { - AddOverload ((ImportSymbolCompletionData)data); - } - - void AddOverload (ImportSymbolCompletionData overload) - { - if (overloads == null) - overloads = new List<CompletionData> (); - overloads.Add (overload); - } - - IEntity IEntityCompletionData.Entity { - get { - return type.GetDefinition (); - } - } - } - - - ICompletionData ICompletionDataFactory.CreateImportCompletionData(IType type, bool useFullName, bool addConstructors) - { - return new ImportSymbolCompletionData (ext, useFullName, type, addConstructors); - } - - } + #endregion - - #region IParameterCompletionDataFactory implementation - IParameterDataProvider IParameterCompletionDataFactory.CreateConstructorProvider (int startOffset, IType type) - { - return new ConstructorParameterDataProvider (startOffset, this, type); - } - - IParameterDataProvider IParameterCompletionDataFactory.CreateConstructorProvider (int startOffset, IType type, AstNode initializer) - { - return new ConstructorParameterDataProvider (startOffset, this, type, initializer); - } - - IParameterDataProvider IParameterCompletionDataFactory.CreateMethodDataProvider (int startOffset, IEnumerable<IMethod> methods) - { - return new MethodParameterDataProvider (startOffset, this, methods); - } - - IParameterDataProvider IParameterCompletionDataFactory.CreateDelegateDataProvider (int startOffset, IType type) - { - return new DelegateDataProvider (startOffset, this, type); - } +*/ - IParameterDataProvider IParameterCompletionDataFactory.CreateIndexerParameterDataProvider (int startOffset, IType type, IEnumerable<IProperty> indexers, AstNode resolvedNode) - { - var arrayType = type as ArrayType; - if (arrayType != null) - return new ArrayTypeParameterDataProvider (startOffset, this, arrayType); - return new IndexerParameterDataProvider (startOffset, this, type, indexers, resolvedNode); - } - - IParameterDataProvider IParameterCompletionDataFactory.CreateTypeParameterDataProvider (int startOffset, IEnumerable<IType> types) - { - return new TypeParameterDataProvider (startOffset, this, types); - } - - IParameterDataProvider IParameterCompletionDataFactory.CreateTypeParameterDataProvider (int startOffset, IEnumerable<IMethod> methods) - { - return new TypeParameterDataProvider (startOffset, this, methods); - } - #endregion #region IDebuggerExpressionResolver implementation - static string GetIdentifierName (TextEditorData editor, Identifier id, out int startOffset) - { - startOffset = editor.LocationToOffset (id.StartLocation.Line, id.StartLocation.Column); - - return editor.GetTextBetween (id.StartLocation, id.EndLocation); - } - - internal static string ResolveExpression (TextEditorData editor, ResolveResult result, AstNode node, out int startOffset) - { - //Console.WriteLine ("result is a {0}", result.GetType ().Name); - startOffset = -1; - - if (result is NamespaceResolveResult || - result is ConversionResolveResult || - result is ConstantResolveResult || - result is ForEachResolveResult || - result is TypeIsResolveResult || - result is TypeOfResolveResult || - result is ErrorResolveResult) - return null; - - if (result.IsCompileTimeConstant) - return null; - - startOffset = editor.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column); - - if (result is InvocationResolveResult) { - var ir = (InvocationResolveResult) result; - if (ir.Member.Name == ".ctor") { - // if the user is hovering over something like "new Abc (...)", we want to show them type information for Abc - return ir.Member.DeclaringType.FullName; - } - - // do not support general method invocation for tooltips because it could cause side-effects - return null; - } else if (result is LocalResolveResult) { - if (node is ParameterDeclaration) { - // user is hovering over a method parameter, but we don't want to include the parameter type - var param = (ParameterDeclaration) node; - - return GetIdentifierName (editor, param.NameToken, out startOffset); - } - - if (node is VariableInitializer) { - // user is hovering over something like "int fubar = 5;", but we don't want the expression to include the " = 5" - var variable = (VariableInitializer) node; - - return GetIdentifierName (editor, variable.NameToken, out startOffset); - } - } else if (result is MemberResolveResult) { - var mr = (MemberResolveResult) result; - - if (node is PropertyDeclaration) { - var prop = (PropertyDeclaration) node; - var name = GetIdentifierName (editor, prop.NameToken, out startOffset); - - // if the property is static, then we want to return "Full.TypeName.Property" - if (prop.Modifiers.HasFlag (Modifiers.Static)) - return mr.Member.DeclaringType.FullName + "." + name; - - // otherwise we want to return "this.Property" so that it won't conflict with anything else in the local scope - return "this." + name; - } - - if (node is FieldDeclaration) { - var field = (FieldDeclaration) node; - var name = GetIdentifierName (editor, field.NameToken, out startOffset); - - // if the field is static, then we want to return "Full.TypeName.Field" - if (field.Modifiers.HasFlag (Modifiers.Static)) - return mr.Member.DeclaringType.FullName + "." + name; - - // otherwise we want to return "this.Field" so that it won't conflict with anything else in the local scope - return "this." + name; - } - - if (node is VariableInitializer) { - // user is hovering over a field declaration that includes initialization - var variable = (VariableInitializer) node; - var name = GetIdentifierName (editor, variable.NameToken, out startOffset); - - // walk up the AST to find the FieldDeclaration so that we can determine if it is static or not - var field = variable.GetParent<FieldDeclaration> (); - - // if the field is static, then we want to return "Full.TypeName.Field" - if (field.Modifiers.HasFlag (Modifiers.Static)) - return mr.Member.DeclaringType.FullName + "." + name; - - // otherwise we want to return "this.Field" so that it won't conflict with anything else in the local scope - return "this." + name; - } - - if (node is NamedExpression) { - // user is hovering over 'Property' in an expression like: var fubar = new Fubar () { Property = baz }; - var variable = node.GetParent<VariableInitializer> (); - if (variable != null) { - var variableName = GetIdentifierName (editor, variable.NameToken, out startOffset); - var name = GetIdentifierName (editor, ((NamedExpression) node).NameToken, out startOffset); - - return variableName + "." + name; - } - } - } else if (result is TypeResolveResult) { - return ((TypeResolveResult) result).Type.FullName; - } - - return editor.GetTextBetween (node.StartLocation, node.EndLocation); - } - - static bool TryResolveAt (Document doc, DocumentLocation loc, out ResolveResult result, out AstNode node) - { - if (doc == null) - throw new ArgumentNullException ("doc"); - - result = null; - node = null; - - var parsedDocument = doc.ParsedDocument; - if (parsedDocument == null) - return false; - - var unit = parsedDocument.GetAst<SyntaxTree> (); - var parsedFile = parsedDocument.ParsedFile as CSharpUnresolvedFile; - - if (unit == null || parsedFile == null) - return false; - - try { - result = ResolveAtLocation.Resolve (new Lazy<ICompilation> (() => doc.Compilation), parsedFile, unit, loc, out node); - if (result == null || node is Statement) - return false; - } catch { - return false; - } - - return true; - } - - string IDebuggerExpressionResolver.ResolveExpression (TextEditorData editor, Document doc, int offset, out int startOffset) + async Task<DebugDataTipInfo> IDebuggerExpressionResolver.ResolveExpressionAsync (IReadonlyTextDocument editor, DocumentContext doc, int offset, CancellationToken cancellationToken) { - ResolveResult result; - AstNode node; - - var loc = editor.OffsetToLocation (offset); - if (!TryResolveAt (doc, loc, out result, out node)) { - startOffset = -1; - return null; - } - - return ResolveExpression (editor, result, node, out startOffset); + return await Resolver.DebuggerExpressionResolver.ResolveAsync (editor, doc, offset, cancellationToken); } #endregion @@ -1501,16 +1088,15 @@ namespace MonoDevelop.CSharp.Completion #region TypeSystemSegmentTree TypeSystemSegmentTree validTypeSystemSegmentTree; - TypeSystemSegmentTree unstableTypeSystemSegmentTree; internal class TypeSystemTreeSegment : TreeSegment { - public IUnresolvedEntity Entity { + public SyntaxNode Entity { get; private set; } - public TypeSystemTreeSegment (int offset, int length, IUnresolvedEntity entity) : base (offset, length) + public TypeSystemTreeSegment (int offset, int length, SyntaxNode entity) : base (offset, length) { this.Entity = entity; } @@ -1519,8 +1105,6 @@ namespace MonoDevelop.CSharp.Completion internal TypeSystemTreeSegment GetMemberSegmentAt (int offset) { TypeSystemTreeSegment result = null; - if (unstableTypeSystemSegmentTree != null) - result = unstableTypeSystemSegmentTree.GetMemberSegmentAt (offset); if (result == null && validTypeSystemSegmentTree != null) result = validTypeSystemSegmentTree.GetMemberSegmentAt (offset); return result; @@ -1528,174 +1112,147 @@ namespace MonoDevelop.CSharp.Completion internal class TypeSystemSegmentTree : SegmentTree<TypeSystemTreeSegment> { - public IUnresolvedTypeDefinition GetTypeAt (int offset) - { - IUnresolvedTypeDefinition result = null; - foreach (var seg in GetSegmentsAt (offset).Where (s => s.Entity is IUnresolvedTypeDefinition)) { - if (result == null || result.Region.IsInside (seg.Entity.Region.Begin)) - result = (IUnresolvedTypeDefinition)seg.Entity; - } - return result; - } - - public IUnresolvedMember GetMemberAt (int offset) + public SyntaxNode GetMemberAt (int offset) { // Members don't overlap - var seg = GetSegmentsAt (offset).FirstOrDefault (s => s.Entity is IUnresolvedMember); + var seg = GetSegmentsAt (offset).FirstOrDefault (); if (seg == null) return null; - return (IUnresolvedMember)seg.Entity; + return seg.Entity; } public TypeSystemTreeSegment GetMemberSegmentAt (int offset) { - // Members don't overlap - var seg = GetSegmentsAt (offset).FirstOrDefault (s => s.Entity is IUnresolvedMember); - if (seg == null) - return null; - return seg; + return GetSegmentsAt (offset).LastOrDefault (); } - internal static TypeSystemSegmentTree Create (ParsedDocument parsedDocument, TextEditorData textEditorData) - { - TypeSystemSegmentTree result = new TypeSystemSegmentTree (); - - foreach (var type in parsedDocument.TopLevelTypeDefinitions) - AddType (textEditorData, result, type); - - return result; - } - static void AddType (TextEditorData textEditorData, TypeSystemSegmentTree result, IUnresolvedTypeDefinition type) + internal static TypeSystemSegmentTree Create (MonoDevelop.Ide.Editor.TextEditor editor, DocumentContext ctx, SemanticModel semanticModel) { - int offset = textEditorData.LocationToOffset (type.Region.Begin); - int endOffset = type.Region.End.IsEmpty ? int.MaxValue : textEditorData.LocationToOffset (type.Region.End); - if (endOffset < 0) - endOffset = int.MaxValue; - result.Add (new TypeSystemTreeSegment (offset, endOffset - offset, type)); - foreach (var entity in type.Members) { - if (entity.IsSynthetic) - continue; - offset = textEditorData.LocationToOffset (entity.Region.Begin); - endOffset = textEditorData.LocationToOffset (entity.Region.End); - if (endOffset < 0) - endOffset = int.MaxValue; - result.Add (new TypeSystemTreeSegment (offset, endOffset - offset, entity)); - } - - foreach (var nested in type.NestedTypes) - AddType (textEditorData, result, nested); + var visitor = new TreeVisitor (); + visitor.Visit (semanticModel.SyntaxTree.GetRoot ()); + return visitor.Result; } - } - - public IUnresolvedTypeDefinition GetTypeAt (int offset) - { - if (unstableTypeSystemSegmentTree == null && validTypeSystemSegmentTree == null) - return null; - IUnresolvedTypeDefinition type = null; - if (unstableTypeSystemSegmentTree != null) - type = unstableTypeSystemSegmentTree.GetTypeAt (offset); - if (type == null && validTypeSystemSegmentTree != null) - type = validTypeSystemSegmentTree.GetTypeAt (offset); - return type; - } - - public IUnresolvedMember GetMemberAt (int offset) - { - if (unstableTypeSystemSegmentTree == null && validTypeSystemSegmentTree == null) - return null; - IUnresolvedMember member = null; - if (unstableTypeSystemSegmentTree != null) - member = unstableTypeSystemSegmentTree.GetMemberAt (offset); - if (member == null && validTypeSystemSegmentTree != null) - member = validTypeSystemSegmentTree.GetMemberAt (offset); + class TreeVisitor : CSharpSyntaxWalker + { + public TypeSystemSegmentTree Result = new TypeSystemSegmentTree (); - return member; - } - #endregion + public override void VisitClassDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.ClassDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + base.VisitClassDeclaration (node); + } + public override void VisitStructDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.StructDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + base.VisitStructDeclaration (node); + } + public override void VisitInterfaceDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.InterfaceDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + base.VisitInterfaceDeclaration (node); + } - class CompletionContextProvider : ICompletionContextProvider - { - readonly ParsedDocument parsedDocument; - readonly TextEditorData textEditorData; - readonly TypeSystemSegmentTree validTypeSystemSegmentTree; - readonly TypeSystemSegmentTree unstableTypeSystemSegmentTree; + public override void VisitEnumDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.EnumDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + } - public CompletionContextProvider (ParsedDocument parsedDocument, TextEditorData textEditorData, - TypeSystemSegmentTree validTypeSystemSegmentTree, TypeSystemSegmentTree unstableTypeSystemSegmentTree) - { - this.parsedDocument = parsedDocument; - this.textEditorData = textEditorData; - this.validTypeSystemSegmentTree = validTypeSystemSegmentTree; - this.unstableTypeSystemSegmentTree = unstableTypeSystemSegmentTree; - } + public override void VisitPropertyDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.PropertyDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + } - IList<string> ICompletionContextProvider.ConditionalSymbols { - get { - return parsedDocument.GetAst<SyntaxTree> ().ConditionalSymbols; + public override void VisitMethodDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); } - } - void ICompletionContextProvider.GetCurrentMembers (int offset, out IUnresolvedTypeDefinition currentType, out IUnresolvedMember currentMember) - { - currentType = GetTypeAt (offset); - currentMember = GetMemberAt (offset); - } + public override void VisitConstructorDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.ConstructorDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + } - public IUnresolvedTypeDefinition GetTypeAt (int offset) - { - if (unstableTypeSystemSegmentTree == null && validTypeSystemSegmentTree == null) - return null; - IUnresolvedTypeDefinition type = null; - if (unstableTypeSystemSegmentTree != null) - type = unstableTypeSystemSegmentTree.GetTypeAt (offset); - if (type == null && validTypeSystemSegmentTree != null) - type = validTypeSystemSegmentTree.GetTypeAt (offset); - return type; - } + public override void VisitDestructorDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.DestructorDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + } - public IUnresolvedMember GetMemberAt (int offset) - { - if (unstableTypeSystemSegmentTree == null && validTypeSystemSegmentTree == null) - return null; + public override void VisitIndexerDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.IndexerDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + } - IUnresolvedMember member = null; - if (unstableTypeSystemSegmentTree != null) - member = unstableTypeSystemSegmentTree.GetMemberAt (offset); - if (member == null && validTypeSystemSegmentTree != null) - member = validTypeSystemSegmentTree.GetMemberAt (offset); - return member; - } + public override void VisitDelegateDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.DelegateDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + } - Tuple<string, TextLocation> ICompletionContextProvider.GetMemberTextToCaret (int caretOffset, IUnresolvedTypeDefinition currentType, IUnresolvedMember currentMember) - { - int startOffset; - if (currentMember != null && currentType != null && currentType.Kind != TypeKind.Enum) { - startOffset = textEditorData.LocationToOffset(currentMember.Region.Begin); - } else if (currentType != null) { - startOffset = textEditorData.LocationToOffset(currentType.Region.Begin); - } else { - startOffset = 0; + public override void VisitOperatorDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.OperatorDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); } - while (startOffset > 0) { - char ch = textEditorData.GetCharAt(startOffset - 1); - if (ch != ' ' && ch != '\t') { - break; - } - --startOffset; + + public override void VisitEventDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.EventDeclarationSyntax node) + { + Result.Add (new TypeSystemTreeSegment (node.SpanStart, node.Span.Length, node)); + } + + public override void VisitBlock (Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax node) + { + // nothing } - return Tuple.Create (caretOffset > startOffset ? textEditorData.GetTextAt (startOffset, caretOffset - startOffset) : "", - (TextLocation)textEditorData.OffsetToLocation (startOffset)); } + + } + + public SyntaxNode GetMemberAt (int offset) + { + SyntaxNode member = null; + if (member == null && validTypeSystemSegmentTree != null) + member = validTypeSystemSegmentTree.GetMemberAt (offset); + return member; + } + #endregion + + - CSharpAstResolver ICompletionContextProvider.GetResolver (CSharpResolver resolver, AstNode rootNode) - { - return new CSharpAstResolver (resolver, rootNode, parsedDocument.ParsedFile as CSharpUnresolvedFile); + [CommandHandler(RefactoryCommands.ImportSymbol)] + void ImportSymbolCommand () + { + if (Editor.SelectionMode == SelectionMode.Block) + return; + var analysisDocument = DocumentContext.AnalysisDocument; + if (analysisDocument == null) + return; + var offset = Editor.CaretOffset; + + ICompletionDataList completionList = null; + int cpos, wlen; + if (!GetCompletionCommandOffset (out cpos, out wlen)) { + cpos = Editor.CaretOffset; + wlen = 0; } + currentCompletionContext = CompletionWidget.CreateCodeCompletionContext (cpos); + currentCompletionContext.TriggerWordLength = wlen; + + var list = new CSharpCompletionDataList (); + list.TriggerWordLength = wlen; + var partialDoc = WithFrozenPartialSemanticsAsync (analysisDocument, default (CancellationToken)).Result; + var semanticModel = partialDoc.GetSemanticModelAsync ().Result; + + AddImportCompletionData (list, semanticModel, offset); + + completionList = CodeCompletionCommand (currentCompletionContext); + if (completionList != null) + CompletionWindowManager.ShowWindow (this, (char)0, completionList, CompletionWidget, currentCompletionContext); + else + currentCompletionContext = null; } + } } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CastCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CastCompletionData.cs new file mode 100644 index 0000000000..33e486a9f8 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CastCompletionData.cs @@ -0,0 +1,76 @@ +// +// CSharpCompletionTextEditorExtension.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2011 Xamarin <http://xamarin.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Microsoft.CodeAnalysis; +using MonoDevelop.Core; +using MonoDevelop.Ide.CodeCompletion; +using System.Collections.Generic; +using System.Linq; +using MonoDevelop.Ide.TypeSystem; +using MonoDevelop.Ide.Editor.Extension; + +namespace MonoDevelop.CSharp.Completion +{ + class CastCompletionData : RoslynCompletionData + { + readonly CSharpCompletionTextEditorExtension ext; + readonly SemanticModel semanticModel; + readonly ISymbol member; + readonly SyntaxNode nodeToCast; + readonly ITypeSymbol targetType; + + public CastCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, CSharpCompletionTextEditorExtension ext, SemanticModel semanticModel, ISymbol member, SyntaxNode nodeToCast, ITypeSymbol targetType) : base(keyHandler) + { + this.targetType = targetType; + this.nodeToCast = nodeToCast; + this.member = member; + this.semanticModel = semanticModel; + this.ext = ext; + this.DisplayText = member.Name; + } + + public override string GetDisplayDescription (bool isSelected) + { + var description = "<small>(cast to " + targetType.ToMinimalDisplayString (semanticModel, nodeToCast.SpanStart, Ambience.LabelFormat) + ")</small>"; + if (isSelected) + return description; + return "<span foreground=\"darkgray\">" + description + "</span>"; + } + + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor) + { + var editor = ext.Editor; + var offset = window.CodeCompletionContext.TriggerOffset; + using (var undo = editor.OpenUndoGroup ()) { + editor.ReplaceText (offset, editor.CaretOffset - offset, member.Name); + var span = nodeToCast.Span; + var type = targetType.ToMinimalDisplayString (semanticModel, nodeToCast.SpanStart, Ambience.LabelFormat); + editor.ReplaceText (span.Start, span.Length, "((" + type + ")" + nodeToCast + ")"); + } + } + } +} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ConstructorParameterDataProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ConstructorParameterDataProvider.cs index c9d6a2855b..28196b83eb 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ConstructorParameterDataProvider.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ConstructorParameterDataProvider.cs @@ -43,7 +43,7 @@ namespace MonoDevelop.CSharp.Completion { this.type = type; - var ctx = ext.CSharpUnresolvedFile.GetTypeResolveContext (ext.UnresolvedFileCompilation, ext.Document.Editor.Caret.Location) as CSharpTypeResolveContext; + var ctx = ext.CSharpUnresolvedFile.GetTypeResolveContext (ext.UnresolvedFileCompilation, ext.Editor.CaretLocation) as CSharpTypeResolveContext; var lookup = new MemberLookup (ctx.CurrentTypeDefinition, ext.Compilation.MainAssembly); bool isProtectedAllowed = false; diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/NewOverrideCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CreateOverrideCompletionData.cs index 4d779caaca..6234f3cade 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/NewOverrideCompletionData.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CreateOverrideCompletionData.cs @@ -1,4 +1,4 @@ -// NewOverrideCompletionData.cs +// CreateOverrideCompletionData.cs // // Author: // Mike Krüger <mkrueger@novell.com> @@ -24,65 +24,86 @@ // THE SOFTWARE. // -using System; using System.Linq; -using System.Text; using MonoDevelop.Ide.CodeCompletion; +using Microsoft.CodeAnalysis; using MonoDevelop.Ide.Gui; using MonoDevelop.Ide.Gui.Content; using System.Collections.Generic; -using ICSharpCode.NRefactory.CSharp; -using Mono.TextEditor; -using ICSharpCode.NRefactory.TypeSystem; using MonoDevelop.Ide.TypeSystem; +using MonoDevelop.Ide.Editor.Extension; +using MonoDevelop.CSharp.Refactoring; +using MonoDevelop.CSharp.Formatting; namespace MonoDevelop.CSharp.Completion { - class NewOverrideCompletionData : CompletionData + class CreateOverrideCompletionData : RoslynSymbolCompletionData { - CSharpCompletionTextEditorExtension ext; - IMember member; - static Ambience ambience = new CSharpAmbience (); - int declarationBegin; - IUnresolvedTypeDefinition type; - + readonly int declarationBegin; + readonly ITypeSymbol currentType; + + bool afterKeyword; + public bool GenerateBody { get; set; } - public override TooltipInformation CreateTooltipInformation (bool smartWrap) - { - return MemberCompletionData.CreateTooltipInformation (ext, null, member, smartWrap); + string displayText; + public override string DisplayText { + get { + if (displayText == null) { + var model = ext.ParsedDocument.GetAst<SemanticModel> (); + displayText = base.Symbol.ToMinimalDisplayString (model, ext.Editor.CaretOffset, Ambience.LabelFormat) + " {...}"; + if (!afterKeyword) + displayText = "override " + displayText; + } + + return displayText; + } } - public NewOverrideCompletionData (CSharpCompletionTextEditorExtension ext, int declarationBegin, IUnresolvedTypeDefinition type, IMember member) : base (null) + public override string GetDisplayTextMarkup () { - this.ext = ext; - this.type = type; - this.member = member; + var model = ext.ParsedDocument.GetAst<SemanticModel> (); + + var result = base.Symbol.ToMinimalDisplayString (model, ext.Editor.CaretOffset, Ambience.LabelFormat) + " {...}"; + var idx = result.IndexOf (Symbol.Name); + if (idx >= 0) { + result = + result.Substring(0, idx) + + "<b>" + Symbol.Name + "</b>"+ + result.Substring(idx + Symbol.Name.Length); + } + + if (!afterKeyword) + result = "override " + result; + return ApplyDiplayFlagsFormatting (result); + } + + public CreateOverrideCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, CSharpCompletionTextEditorExtension ext, int declarationBegin, ITypeSymbol currentType, Microsoft.CodeAnalysis.ISymbol member, bool afterKeyword) : base (keyHandler, ext, member, member.ToDisplayString ()) + { + this.afterKeyword = afterKeyword; + this.currentType = currentType; this.declarationBegin = declarationBegin; this.GenerateBody = true; - this.Icon = member.GetStockIcon (); - this.DisplayText = ambience.GetString (member, OutputFlags.IncludeParameters | OutputFlags.IncludeParameterName | OutputFlags.IncludeGenerics | OutputFlags.HideExtensionsParameter| OutputFlags.IncludeAccessor); - this.CompletionText = member.SymbolKind == SymbolKind.Indexer ? "this" : member.Name; } - - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) + + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor) { - var editor = ext.TextEditorData; - var generator = CodeGenerator.CreateGenerator (ext.Document); + var editor = ext.Editor; bool isExplicit = false; - if (member.DeclaringTypeDefinition.Kind == TypeKind.Interface) { - foreach (var m in type.Members) { - if (m.Name == member.Name && !m.ReturnType.Equals (member.ReturnType)) { - isExplicit = true; - break; - } - } - } - var resolvedType = type.Resolve (ext.Project).GetDefinition (); - if (ext.Project != null) - generator.PolicyParent = ext.Project.Policies; - var result = generator.CreateMemberImplementation (resolvedType, type, member, isExplicit); +// if (member.DeclaringTypeDefinition.Kind == TypeKind.Interface) { +// foreach (var m in type.Members) { +// if (m.Name == member.Name && !m.ReturnType.Equals (member.ReturnType)) { +// isExplicit = true; +// break; +// } +// } +// } +// var resolvedType = type.Resolve (ext.Project).GetDefinition (); +// if (ext.Project != null) +// generator.PolicyParent = ext.Project.Policies; + + var result = CSharpCodeGenerator.CreateOverridenMemberImplementation (ext.DocumentContext, ext.Editor, currentType, currentType.Locations.First (), Symbol, isExplicit); string sb = result.Code.TrimStart (); int trimStart = result.Code.Length - sb.Length; sb = sb.TrimEnd (); @@ -107,13 +128,15 @@ namespace MonoDevelop.CSharp.Completion targetCaretPosition = declarationBegin + sb.Length; } - editor.Replace (declarationBegin, editor.Caret.Offset - declarationBegin, sb); + editor.ReplaceText (declarationBegin, editor.CaretOffset - declarationBegin, sb); if (selectionEndPosition > 0) { - editor.Caret.Offset = selectionEndPosition; + editor.CaretOffset = selectionEndPosition; editor.SetSelection (targetCaretPosition, selectionEndPosition); } else { - editor.Caret.Offset = targetCaretPosition; + editor.CaretOffset = targetCaretPosition; } + + OnTheFlyFormatter.Format (editor, ext.DocumentContext, declarationBegin, declarationBegin + sb.Length); } } } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CreatePartialCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CreatePartialCompletionData.cs new file mode 100644 index 0000000000..c2527a03c9 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CreatePartialCompletionData.cs @@ -0,0 +1,133 @@ +// +// CreatePartialCompletionData.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Linq; +using MonoDevelop.Ide.CodeCompletion; +using Microsoft.CodeAnalysis; +using MonoDevelop.CSharp.Formatting; +using MonoDevelop.CSharp.Refactoring; +using MonoDevelop.Ide.TypeSystem; +using MonoDevelop.Ide.Editor.Extension; + +namespace MonoDevelop.CSharp.Completion +{ + class CreatePartialCompletionData : RoslynSymbolCompletionData + { + readonly ITypeSymbol currentType; + readonly int declarationBegin; + + bool afterKeyword; + + public bool GenerateBody { get; set; } + + string displayText; + public override string DisplayText { + get { + if (displayText == null) { + var model = ext.ParsedDocument.GetAst<SemanticModel> (); + displayText = base.Symbol.ToMinimalDisplayString (model, ext.Editor.CaretOffset, Ambience.LabelFormat) + " {...}"; + if (!afterKeyword) + displayText = "partial " + displayText; + } + return displayText; + } + } + + + public override string GetDisplayTextMarkup () + { + var model = ext.ParsedDocument.GetAst<SemanticModel> (); + + var result = base.Symbol.ToMinimalDisplayString (model, ext.Editor.CaretOffset, Ambience.LabelFormat) + " {...}"; + var idx = result.IndexOf (Symbol.Name); + if (idx >= 0) { + result = + result.Substring(0, idx) + + "<b>" + Symbol.Name + "</b>"+ + result.Substring(idx + Symbol.Name.Length); + } + + if (!afterKeyword) + result = "partial " + result; + + return ApplyDiplayFlagsFormatting (result); + } + + public CreatePartialCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, CSharpCompletionTextEditorExtension ext, int declarationBegin, ITypeSymbol currentType, ISymbol member, bool afterKeyword) : base (keyHandler, ext, member) + { + this.afterKeyword = afterKeyword; + this.currentType = currentType; + this.declarationBegin = declarationBegin; + this.GenerateBody = true; + } + + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor) + { + var editor = ext.Editor; + bool isExplicit = false; + // if (member.DeclaringTypeDefinition.Kind == TypeKind.Interface) { + // foreach (var m in type.Members) { + // if (m.Name == member.Name && !m.ReturnType.Equals (member.ReturnType)) { + // isExplicit = true; + // break; + // } + // } + // } + // var resolvedType = type.Resolve (ext.Project).GetDefinition (); + // if (ext.Project != null) + // generator.PolicyParent = ext.Project.Policies; + + var result = CSharpCodeGenerator.CreatePartialMemberImplementation (ext.DocumentContext, ext.Editor, currentType, currentType.Locations.First (), Symbol, isExplicit); + string sb = result.Code.TrimStart (); + int trimStart = result.Code.Length - sb.Length; + sb = sb.TrimEnd (); + + var lastRegion = result.BodyRegions.LastOrDefault (); + var region = lastRegion == null? null + : new CodeGeneratorBodyRegion (lastRegion.StartOffset - trimStart, lastRegion.EndOffset - trimStart); + + int targetCaretPosition; + int selectionEndPosition = -1; + if (region != null && region.IsValid) { + targetCaretPosition = declarationBegin + region.EndOffset; + + } else { + targetCaretPosition = declarationBegin + sb.Length; + } + + editor.ReplaceText (declarationBegin, editor.CaretOffset - declarationBegin, sb); + if (selectionEndPosition > 0) { + editor.CaretOffset = selectionEndPosition; + editor.SetSelection (targetCaretPosition, selectionEndPosition); + } else { + editor.CaretOffset = targetCaretPosition; + } + + OnTheFlyFormatter.Format (editor, ext.DocumentContext, declarationBegin, declarationBegin + sb.Length); + editor.CaretLine--; + } + } +} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/DelegateDataProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/DelegateDataProvider.cs deleted file mode 100644 index 527a7aa8b8..0000000000 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/DelegateDataProvider.cs +++ /dev/null @@ -1,98 +0,0 @@ -// -// DelegateDataProvider.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com> -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Collections.Generic; -using System.Text; -using System.Xml; - -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Ide.CodeCompletion; -using MonoDevelop.CSharp.Formatting; -using MonoDevelop.CSharp.Parser; -using System.Text.RegularExpressions; -using ICSharpCode.NRefactory.CSharp; -using MonoDevelop.CSharp.Resolver; -using Mono.TextEditor; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.CSharp.Resolver; -using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory.Completion; -using System.Linq; -using ICSharpCode.NRefactory.CSharp.TypeSystem; - -namespace MonoDevelop.CSharp.Completion -{ - class DelegateDataProvider : AbstractParameterDataProvider - { -// IType delegateType; - IMethod delegateMethod; - - ICompilation compilation; - CSharpUnresolvedFile file; - - public DelegateDataProvider (int startOffset, CSharpCompletionTextEditorExtension ext, IType delegateType) : base (ext, startOffset) - { - compilation = ext.UnresolvedFileCompilation; - file = ext.CSharpUnresolvedFile; - // this.delegateType = delegateType; - this.delegateMethod = delegateType.GetDelegateInvokeMethod (); - } - - public override TooltipInformation CreateTooltipInformation (int overload, int currentParameter, bool smartWrap) - { - return MethodParameterDataProvider.CreateTooltipInformation (ext, compilation, file, delegateMethod, currentParameter, smartWrap); - } - - #region IParameterDataProvider implementation - public override int GetParameterCount (int overload) - { - if (overload >= Count) - return -1; - return delegateMethod.Parameters != null ? delegateMethod.Parameters.Count : 0; - } - - public override bool AllowParameterList (int overload) - { - if (overload >= Count) - return false; - var lastParam = delegateMethod.Parameters.LastOrDefault (); - return lastParam != null && lastParam.IsParams; - } - - public override string GetParameterName (int overload, int paramIndex) - { - return delegateMethod.Parameters[paramIndex].Name; - } - - public override int Count { - get { - return 1; - } - } - #endregion - } -} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/EventCreationCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/EventCreationCompletionData.cs index ed967df971..f009e5d91e 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/EventCreationCompletionData.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/EventCreationCompletionData.cs @@ -32,109 +32,117 @@ using MonoDevelop.Ide.Gui; using MonoDevelop.Ide.Gui.Content; using MonoDevelop.CSharp.Formatting; using MonoDevelop.CSharp.Parser; -using Mono.TextEditor; using System.Collections.Generic; -using ICSharpCode.NRefactory.TypeSystem; +using MonoDevelop.Ide.Editor; +using MonoDevelop.Core.Text; +using MonoDevelop.Ide.Editor.Util; +using MonoDevelop.Ide.Editor.Extension; +using Microsoft.CodeAnalysis; +using MonoDevelop.Ide; +using MonoDevelop.Refactoring; +using ICSharpCode.NRefactory6.CSharp; +using System.Threading; +using MonoDevelop.Ide.TypeSystem; namespace MonoDevelop.CSharp.Completion { - class EventCreationCompletionData : CompletionData + class EventCreationCompletionData : AnonymousMethodCompletionData { - string parameterList; - IUnresolvedMember callingMember; -// CSharpCompletionTextEditorExtension ext; - int initialOffset; - public bool AddSemicolon = true; - TextEditorData editor; - + readonly CSharpCompletionTextEditorExtension ext; + readonly ITypeSymbol delegateType; + readonly INamedTypeSymbol curType; + readonly string varName; + public override TooltipInformation CreateTooltipInformation (bool smartWrap) { var tooltipInfo = new TooltipInformation (); return tooltipInfo; } - public EventCreationCompletionData (CSharpCompletionTextEditorExtension ext, string methodName, IType delegateType, IEvent evt, string parameterList, IUnresolvedMember callingMember, IUnresolvedTypeDefinition declaringType) : base (null) + public EventCreationCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, CSharpCompletionTextEditorExtension ext, ITypeSymbol delegateType, string varName, INamedTypeSymbol curType) : base (keyHandler) { - if (string.IsNullOrEmpty (methodName)) { - this.DisplayText = (evt != null ? evt.Name : ""); - } else { - this.DisplayText = Char.ToUpper (methodName[0]) + methodName.Substring (1) + (evt != null ? evt.Name : ""); - } - - if (declaringType != null && declaringType.Members.Any (m => m.Name == this.DisplayText)) { - for (int i = 1; i < 10000; i++) { - if (!declaringType.Members.Any (m => m.Name == this.DisplayText + i)) { - this.DisplayText = this.DisplayText + i.ToString (); - break; - } - } - } - this.editor = ext.TextEditorData; - this.parameterList = parameterList; - this.callingMember = callingMember; - this.Icon = "md-newmethod"; - this.initialOffset = editor.Caret.Offset; + this.curType = curType; + this.varName = varName; + this.DisplayText = varName; + this.delegateType = delegateType; + this.ext = ext; + this.Icon = "md-newmethod"; } - - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) + + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor) { // insert add/remove event handler code after +=/-= - editor.Replace (initialOffset, editor.Caret.Offset - initialOffset, this.DisplayText + (AddSemicolon ? ";" : "")); - - // Search opening bracket of member - int pos = callingMember != null && !callingMember.BodyRegion.Begin.IsEmpty ? editor.Document.LocationToOffset (callingMember.BodyRegion.BeginLine, callingMember.BodyRegion.BeginColumn) : initialOffset; - while (pos < editor.Document.TextLength && editor.Document.GetCharAt (pos) != '{') { - pos++; - } - - // Search closing bracket of member - pos = editor.Document.GetMatchingBracketOffset (pos) + 1; - - pos = Math.Max (0, Math.Min (pos, editor.Document.TextLength - 1)); - - // Insert new event handler after closing bracket - var line = callingMember != null ? editor.Document.GetLine (callingMember.Region.BeginLine) : editor.Document.GetLineByOffset (initialOffset); - string indent = line.GetIndentation (editor.Document); - - StringBuilder sb = new StringBuilder (); - sb.Append (editor.EolMarker); - sb.Append (editor.EolMarker); - sb.Append (indent); - if (callingMember != null && callingMember.IsStatic) - sb.Append ("static "); - sb.Append ("void "); - int pos2 = sb.Length; - sb.Append (this.DisplayText); - sb.Append (' '); - sb.Append (this.parameterList); - sb.Append (editor.EolMarker); - sb.Append (indent); - sb.Append ("{"); - sb.Append (editor.EolMarker); - sb.Append (indent); - sb.Append (editor.Options.IndentationString); - int cursorPos = pos + sb.Length; - sb.Append (editor.EolMarker); - sb.Append (indent); - sb.Append ("}"); - editor.Insert (pos, sb.ToString ()); - editor.Caret.Offset = cursorPos; - - // start text link mode after insert - List<TextLink> links = new List<TextLink> (); - TextLink link = new TextLink ("name"); - - link.AddLink (new TextSegment (0, this.DisplayText.Length)); - link.AddLink (new TextSegment (pos - initialOffset + pos2, this.DisplayText.Length)); - links.Add (link); - - var tle = new TextLinkEditMode (editor.Parent, initialOffset, links); - tle.TextLinkMode = TextLinkMode.EditIdentifier; - tle.SetCaretPosition = true; - tle.SelectPrimaryLink = true; - tle.OldMode = editor.CurrentMode; - tle.StartMode (); - editor.CurrentMode = tle; + var editor = ext.Editor; + + + bool AddSemicolon = true; + var position = window.CodeCompletionContext.TriggerOffset; + editor.ReplaceText (position, editor.CaretOffset - position, this.DisplayText + (AddSemicolon ? ";" : "")); + + + var document = IdeApp.Workbench.ActiveDocument; + var parsedDocument = document.UpdateParseDocument (); + var semanticModel = parsedDocument.GetAst<SemanticModel> (); + + var declaringType = semanticModel.GetEnclosingSymbol<INamedTypeSymbol> (position, default(CancellationToken)); + var enclosingSymbol = semanticModel.GetEnclosingSymbol<ISymbol> (position, default(CancellationToken)); + + var insertionPoints = InsertionPointService.GetInsertionPoints ( + document.Editor, + parsedDocument, + declaringType, + declaringType.Locations.First() + ); + + var options = new InsertionModeOptions ( + "Create new method", + insertionPoints, + async point => { + if (!point.Success) + return; + var indent = "\t"; + var sb = new StringBuilder (); + if (enclosingSymbol != null && enclosingSymbol.IsStatic) + sb.Append ("static "); + sb.Append ("void "); + int pos2 = sb.Length; + sb.Append (this.DisplayText); + sb.Append (' '); + sb.Append("("); + + var delegateMethod = delegateType.GetDelegateInvokeMethod(); + for (int k = 0; k < delegateMethod.Parameters.Length; k++) { + if (k > 0) { + sb.Append(", "); + } + sb.Append (delegateMethod.Parameters [k].ToMinimalDisplayString (semanticModel, position, Ambience.LabelFormat)); + } + sb.Append(")"); + + sb.Append (editor.EolMarker); + sb.Append (indent); + sb.Append ("{"); + sb.Append (editor.EolMarker); + sb.Append (indent); + sb.Append (editor.Options.GetIndentationString ()); + //int cursorPos = pos + sb.Length; + sb.Append (editor.EolMarker); + sb.Append (indent); + sb.Append ("}"); + point.InsertionPoint.Insert (document.Editor, document, sb.ToString ()); + // // start text link mode after insert + // var links = new List<TextLink> (); + // var link = new TextLink ("name"); + // + // link.AddLink (new TextSegment (initialOffset, this.DisplayText.Length)); + // link.AddLink (new TextSegment (initialOffset + pos + pos2, this.DisplayText.Length)); + // links.Add (link); + // editor.StartTextLinkMode (new TextLinkModeOptions (links)); + } + ); + + editor.StartInsertionMode (options); + } } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ImportSymbolCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ImportSymbolCompletionData.cs new file mode 100644 index 0000000000..83ae1d8660 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ImportSymbolCompletionData.cs @@ -0,0 +1,161 @@ +// +// ImportSymbolCompletionData.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using MonoDevelop.Ide.CodeCompletion; +using Microsoft.CodeAnalysis; +using GLib; +using System.Collections.Generic; +using MonoDevelop.Core; +using MonoDevelop.Ide.TypeSystem; +using MonoDevelop.Components.PropertyGrid.PropertyEditors; +using MonoDevelop.Ide.Editor; +using System.Text; + +namespace MonoDevelop.CSharp.Completion +{ + class ImportSymbolCompletionData : RoslynCompletionData + { + CSharpCompletionTextEditorExtension ext; + INamedTypeSymbol type; + bool useFullName; + + public override IconId Icon { + get { + return type.GetStockIcon (); + } + } + + public override int PriorityGroup { get { return int.MinValue; } } + + public ImportSymbolCompletionData (CSharpCompletionTextEditorExtension ext, INamedTypeSymbol type, bool useFullName) : base (null, type.Name) + { + this.ext = ext; + this.useFullName = useFullName; + this.type = type; + this.DisplayFlags |= DisplayFlags.IsImportCompletion; + } + + bool initialized = false; + bool generateUsing, insertNamespace; + + void Initialize () + { + if (initialized) + return; + initialized = true; + if (type.ContainingNamespace == null) + return; + generateUsing = !useFullName; + insertNamespace = useFullName; + } + + static string GetDefaultDisplaySelection (string description, bool isSelected) + { + if (!isSelected) + return "<span foreground=\"darkgray\">" + description + "</span>"; + return description; + } + + string displayDescription = null; + public override string GetDisplayDescription (bool isSelected) + { + if (displayDescription == null) { + Initialize (); + if (generateUsing || insertNamespace) { + displayDescription = string.Format (GettextCatalog.GetString ("(from '{0}')"), type.ContainingNamespace.Name); + } else { + displayDescription = ""; + } + } + return GetDefaultDisplaySelection (displayDescription, isSelected); + } + + #region IActionCompletionData implementation + + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, MonoDevelop.Ide.Editor.Extension.KeyDescriptor descriptor) + { + Initialize (); + var doc = ext.DocumentContext; + using (var undo = ext.Editor.OpenUndoGroup ()) { + string text = insertNamespace ? type.ContainingNamespace.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat) + "." + type.Name : type.Name; + if (text != GetCurrentWord (window)) { + if (window.WasShiftPressed && generateUsing) + text = type.ContainingNamespace.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat) + "." + text; + window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, GetCurrentWord (window), text); + } + + if (!window.WasShiftPressed && generateUsing) { + AddGlobalNamespaceImport (ext.Editor, doc, type.ContainingNamespace.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat)); + } + } + ka |= KeyActions.Ignore; + } + + static void AddGlobalNamespaceImport (MonoDevelop.Ide.Editor.TextEditor editor, DocumentContext context, string nsName) + { + var parsedDocument = context.ParsedDocument; + var unit = parsedDocument.GetAst<SemanticModel> (); + if (unit == null) + return; + + int offset = SearchUsingInsertionPoint (unit.SyntaxTree.GetRoot ()); + + var text = new StringBuilder (); + text.Append ("using "); + text.Append (nsName); + text.Append (";"); + text.Append (editor.EolMarker); + + editor.InsertText (offset, text.ToString ()); + } + + static int SearchUsingInsertionPoint (SyntaxNode parent) + { + var result = 0; + foreach (SyntaxNode node in parent.ChildNodes ()) { + if (node.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.UsingDirective)) { + result = node.FullSpan.End; + continue; + } + SyntaxTrivia last = new SyntaxTrivia (); + + foreach (var trivia in node.GetLeadingTrivia ()) { + if (last.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.SingleLineCommentTrivia)|| + last.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.DefineDirectiveTrivia) || + last.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.MultiLineCommentTrivia) || + last.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.SingleLineDocumentationCommentTrivia)) + result = trivia.Span.End; + last = trivia; + } + break; + } + return result; + } + #endregion + } +} + diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/IndexerParameterDataProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/IndexerParameterDataProvider.cs deleted file mode 100644 index 38bb78ff5f..0000000000 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/IndexerParameterDataProvider.cs +++ /dev/null @@ -1,99 +0,0 @@ -// -// NRefactoryIndexerParameterDataProvider.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Text; -using System.Xml; - -using MonoDevelop.Ide.Gui; -using MonoDevelop.Ide.CodeCompletion; -using MonoDevelop.CSharp.Formatting; -using MonoDevelop.CSharp.Parser; - -using System.Text.RegularExpressions; -using ICSharpCode.NRefactory.CSharp; -using Mono.TextEditor; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.Completion; -using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory.CSharp.TypeSystem; - -namespace MonoDevelop.CSharp.Completion -{ - class IndexerParameterDataProvider : AbstractParameterDataProvider - { -// AstNode resolvedExpression; - List<IProperty> indexers; - - ICompilation compilation; - CSharpUnresolvedFile file; - - public IndexerParameterDataProvider (int startOffset, CSharpCompletionTextEditorExtension ext, IType type, IEnumerable<IProperty> indexers, AstNode resolvedExpression) : base (ext, startOffset) - { - compilation = ext.UnresolvedFileCompilation; - file = ext.CSharpUnresolvedFile; - // this.resolvedExpression = resolvedExpression; - this.indexers = new List<IProperty> (indexers); - } - - public override TooltipInformation CreateTooltipInformation (int overload, int currentParameter, bool smartWrap) - { - return MethodParameterDataProvider.CreateTooltipInformation (ext, compilation, file, indexers[overload], currentParameter, smartWrap); - } - - #region IParameterDataProvider implementation - public override int GetParameterCount (int overload) - { - if (overload >= Count) - return -1; - var indexer = indexers[overload]; - return indexer != null && indexer.Parameters != null ? indexer.Parameters.Count : 0; - } - - public override bool AllowParameterList (int overload) - { - if (overload >= Count) - return false; - var lastParam = indexers[overload].Parameters.LastOrDefault (); - return lastParam != null && lastParam.IsParams; - } - - public override string GetParameterName (int overload, int paramIndex) - { - var indexer = indexers[overload]; - return indexer.Parameters[paramIndex].Name; - } - - public override int Count { - get { - return indexers != null ? indexers.Count : 0; - } - } - #endregion - } -} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MemberCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MemberCompletionData.cs deleted file mode 100644 index ab85e91705..0000000000 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MemberCompletionData.cs +++ /dev/null @@ -1,864 +0,0 @@ -// MemberCompletionData.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Xml; -using MonoDevelop.Ide.CodeCompletion; -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Ide.Gui.Content; -using ICSharpCode.NRefactory.CSharp; -using Mono.TextEditor; -using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.Projects; -using ICSharpCode.NRefactory.Completion; -using ICSharpCode.NRefactory.Documentation; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.CSharp.TypeSystem; -using System.IO; -using MonoDevelop.CSharp.Formatting; -using Gtk; -using MonoDevelop.Ide; - -namespace MonoDevelop.CSharp.Completion -{ - class MemberCompletionData : CompletionData, IEntityCompletionData - { - CSharpCompletionTextEditorExtension editorCompletion; - OutputFlags flags; - bool hideExtensionParameter = true; - static CSharpAmbience ambience = new CSharpAmbience (); - string completionString; - string displayText; - Dictionary<string, CompletionData> overloads; - - Mono.TextEditor.TextEditorData Editor { - get { - return editorCompletion.TextEditorData; - } - } - - MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy Policy { - get { - return editorCompletion.FormattingPolicy; - } - } - - public override string Description { - get { - return ""; - } - } - - public override string CompletionText { - get { return completionString; } - set { completionString = value; } - } - - public override string DisplayText { - get { - if (displayText == null) { - displayText = ambience.GetString (Entity.SymbolKind == SymbolKind.Constructor ? Entity.DeclaringTypeDefinition : Entity, flags | OutputFlags.HideGenericParameterNames); - } - return displayText; - } - } - - public override IconId Icon { - get { - return (Entity.SymbolKind == SymbolKind.Constructor ? Entity.DeclaringTypeDefinition : Entity).GetStockIcon (); - } - } - - public bool HideExtensionParameter { - get { - return hideExtensionParameter; - } - set { - hideExtensionParameter = value; - } - } - - bool isDelegateExpected; - public bool IsDelegateExpected { - get { - return isDelegateExpected || factory != null && factory.Engine.PossibleDelegates.Count > 0; - } - set { - isDelegateExpected = value; - } - } - - ICompilation compilation; - CSharpUnresolvedFile file; - CSharpCompletionTextEditorExtension.CompletionDataFactory factory; - - public MemberCompletionData (CSharpCompletionTextEditorExtension.CompletionDataFactory factory, IEntity entity, OutputFlags flags) : this(factory.ext, entity, flags) - { - this.factory = factory; - } - - public MemberCompletionData (CSharpCompletionTextEditorExtension editorCompletion, IEntity entity, OutputFlags flags) - { - compilation = editorCompletion.UnresolvedFileCompilation; - file = editorCompletion.CSharpUnresolvedFile; - - this.editorCompletion = editorCompletion; - this.flags = flags; - SetMember (entity); - DisplayFlags = DisplayFlags.DescriptionHasMarkup; - var m = Entity as IMember; - if (m != null && m.IsObsolete ()) - DisplayFlags |= DisplayFlags.Obsolete; - } - - public bool SearchBracket (int start, out int pos) - { - pos = -1; - - for (int i = start; i < Editor.Length; i++) { - char ch = Editor.GetCharAt (i); - if (ch == '(') { - pos = i + 1; - return true; - } - if (!char.IsWhiteSpace (ch)) - return false; - } - return false; - } - - static bool HasNonMethodMembersWithSameName (IMember member) - { - return member.DeclaringType.GetFields ().Cast<INamedElement> () - .Concat (member.DeclaringType.GetProperties ().Cast<INamedElement> ()) - .Concat (member.DeclaringType.GetEvents ().Cast<INamedElement> ()) - .Concat (member.DeclaringType.GetNestedTypes ().Cast<INamedElement> ()) - .Any (e => e.Name == member.Name); - } - - static bool HasAnyOverloadWithParameters (IMethod method) - { - if (method.SymbolKind == SymbolKind.Constructor) - return method.DeclaringType.GetConstructors ().Any (m => m.Parameters.Count > 0); - return method.DeclaringType.GetMethods ().Any (m => m.Name == method.Name && m.Parameters.Count > 0); - } - - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) - { - InsertCompletionText (window, ref ka, closeChar, keyChar, modifier, CompletionTextEditorExtension.AddParenthesesAfterCompletion, CompletionTextEditorExtension.AddOpeningOnly); - } - - bool IsBracketAlreadyInserted (IMethod method) - { - int offset = Editor.Caret.Offset; - while (offset < Editor.Length) { - char ch = Editor.GetCharAt (offset); - if (!char.IsLetterOrDigit (ch)) - break; - offset++; - } - while (offset < Editor.Length) { - char ch = Editor.GetCharAt (offset); - if (!char.IsWhiteSpace (ch)) - return ch == '(' || ch == '<' && RequireGenerics (method); - offset++; - } - return false; - } - - bool InsertSemicolon (int exprStart) - { - int offset = exprStart; - while (offset > 0) { - char ch = Editor.GetCharAt (offset); - if (!char.IsWhiteSpace (ch)) { - if (ch != '{' && ch != '}' && ch != ';') - return false; - break; - } - offset--; - } - - offset = Editor.Caret.Offset; - while (offset < Editor.Length) { - char ch = Editor.GetCharAt (offset); - if (!char.IsLetterOrDigit (ch)) - break; - offset++; - } - while (offset < Editor.Length) { - char ch = Editor.GetCharAt (offset); - if (!char.IsWhiteSpace (ch)) - return char.IsLetter (ch) || ch == '}'; - offset++; - } - return true; - } - - public void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier, bool addParens, bool addOpeningOnly) - { - string text = CompletionText; - string partialWord = GetCurrentWord (window); - int skipChars = 0; - bool runParameterCompletionCommand = false; - bool runCompletionCompletionCommand = false; - var method = Entity as IMethod; - if (addParens && !IsDelegateExpected && method != null && !HasNonMethodMembersWithSameName ((IMember)Entity) && !IsBracketAlreadyInserted (method)) { - var line = Editor.GetLine (Editor.Caret.Line); - //var start = window.CodeCompletionContext.TriggerOffset + partialWord.Length + 2; - //var end = line.Offset + line.Length; - //string textToEnd = start < end ? Editor.GetTextBetween (start, end) : ""; - bool addSpace = Policy.BeforeMethodCallParentheses && CSharpTextEditorIndentation.OnTheFlyFormatting; - - int exprStart = window.CodeCompletionContext.TriggerOffset - 1; - while (exprStart > line.Offset) { - char ch = Editor.GetCharAt (exprStart); - if (ch != '.' && ch != '_' && /*ch != '<' && ch != '>' && */!char.IsLetterOrDigit (ch)) - break; - exprStart--; - } - bool insertSemicolon = InsertSemicolon(exprStart); - if (Entity.SymbolKind == SymbolKind.Constructor) - insertSemicolon = false; - //int pos; - - Gdk.Key[] keys = new [] { Gdk.Key.Return, Gdk.Key.Tab, Gdk.Key.space, Gdk.Key.KP_Enter, Gdk.Key.ISO_Enter }; - if (keys.Contains (closeChar) || keyChar == '.') { - if (HasAnyOverloadWithParameters (method)) { - if (addOpeningOnly) { - text += RequireGenerics (method) ? "<|" : (addSpace ? " (|" : "(|"); - skipChars = 0; - } else { - if (keyChar == '.') { - if (RequireGenerics (method)) { - text += addSpace ? "<> ()" : "<>()"; - } else { - text += addSpace ? " ()" : "()"; - } - skipChars = 0; - } else { - if (insertSemicolon) { - if (RequireGenerics (method)) { - text += addSpace ? "<|> ();" : "<|>();"; - skipChars = addSpace ? 5 : 4; - } else { - text += addSpace ? " (|);" : "(|);"; - skipChars = 2; - } - } else { - if (RequireGenerics (method)) { - text += addSpace ? "<|> ()" : "<|>()"; - skipChars = addSpace ? 4 : 3; - } else { - text += addSpace ? " (|)" : "(|)"; - skipChars = 1; - } - } - } - } - runParameterCompletionCommand = true; - } else { - if (addOpeningOnly) { - text += RequireGenerics (method) ? "<|" : (addSpace ? " (|" : "(|"); - skipChars = 0; - } else { - if (keyChar == '.') { - if (RequireGenerics (method)) { - text += addSpace ? "<> ().|" : "<>().|"; - } else { - text += addSpace ? " ().|" : "().|"; - } - skipChars = 0; - } else { - if (insertSemicolon) { - if (RequireGenerics (method)) { - text += addSpace ? "<|> ();" : "<|>();"; - } else { - text += addSpace ? " ();|" : "();|"; - } - - } else { - if (RequireGenerics (method)) { - text += addSpace ? "<|> ()" : "<|>()"; - } else { - text += addSpace ? " ()|" : "()|"; - } - - } - } - } - } - if (keyChar == '(') { - var skipChar = Editor.SkipChars.LastOrDefault (); - if (skipChar != null && skipChar.Offset == (window.CodeCompletionContext.TriggerOffset + partialWord.Length) && skipChar.Char == ')') - Editor.Remove (skipChar.Offset, 1); - } - } - ka |= KeyActions.Ignore; - } - if ((DisplayFlags & DisplayFlags.NamedArgument) == DisplayFlags.NamedArgument && - CompletionTextEditorExtension.AddParenthesesAfterCompletion && - (closeChar == Gdk.Key.Tab || - closeChar == Gdk.Key.KP_Tab || - closeChar == Gdk.Key.ISO_Left_Tab || - closeChar == Gdk.Key.Return || - closeChar == Gdk.Key.KP_Enter || - closeChar == Gdk.Key.ISO_Enter || - closeChar == Gdk.Key.space || - closeChar == Gdk.Key.KP_Space)) { - if (Policy.AroundAssignmentParentheses) - text += " "; - text += "="; - if (Policy.AroundAssignmentParentheses && !(closeChar == Gdk.Key.space || closeChar == Gdk.Key.KP_Space)) - text += " "; - runCompletionCompletionCommand = true; - } - window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, partialWord, text); - int offset = Editor.Caret.Offset; - for (int i = 0; i < skipChars; i++) { - Editor.SetSkipChar (offset, Editor.GetCharAt (offset)); - offset++; - } - - if (runParameterCompletionCommand) - editorCompletion.RunParameterCompletionCommand (); - if (runCompletionCompletionCommand && IdeApp.Workbench != null) { - Application.Invoke (delegate { - editorCompletion.RunCompletionCommand (); - }); - } - } - - bool ContainsType (IType testType, IType searchType) - { - if (testType == searchType) - return true; - foreach (var arg in testType.TypeArguments) - if (ContainsType (arg, searchType)) - return true; - return false; - } - - bool RequireGenerics (IMethod method) - { - if (method.SymbolKind == SymbolKind.Constructor) - return method.DeclaringType.TypeParameterCount > 0; - var testMethod = method.ReducedFrom ?? method; - return testMethod.TypeArguments.Any (t => !testMethod.Parameters.Any (p => ContainsType(p.Type, t))); - } - - void SetMember (IEntity entity) - { - this.Entity = entity; - this.completionString = displayText = (Entity.SymbolKind == SymbolKind.Constructor ? Entity.DeclaringTypeDefinition : Entity).Name; - } - - TypeSystemAstBuilder GetBuilder (ICompilation compilation) - { - var ctx = editorCompletion.CSharpUnresolvedFile.GetTypeResolveContext (editorCompletion.UnresolvedFileCompilation, editorCompletion.Document.Editor.Caret.Location) as CSharpTypeResolveContext; - var state = new CSharpResolver (ctx); - var builder = new TypeSystemAstBuilder (state); - builder.AddAnnotations = true; - var dt = state.CurrentTypeDefinition; - var declaring = ctx.CurrentTypeDefinition != null ? ctx.CurrentTypeDefinition.DeclaringTypeDefinition : null; - if (declaring != null) { - while (dt != null) { - if (dt.Equals (declaring)) { - builder.AlwaysUseShortTypeNames = true; - break; - } - dt = dt.DeclaringTypeDefinition; - } - } - return builder; - } - - internal class MyAmbience : IAmbience - { - TypeSystemAstBuilder builder; - - public MyAmbience (TypeSystemAstBuilder builder) - { - this.builder = builder; - ConversionFlags = ICSharpCode.NRefactory.TypeSystem.ConversionFlags.StandardConversionFlags; - } - - public ConversionFlags ConversionFlags { get; set; } - #region ConvertEntity - public string ConvertSymbol(ISymbol symbol) - { - if (symbol is IEntity) - return ConvertEntity ((IEntity)symbol); - return symbol.ToString (); - } - - public string ConvertEntity (IEntity entity) - { - if (entity == null) - throw new ArgumentNullException ("entity"); - - StringWriter writer = new StringWriter (); - ConvertEntity (entity, new TextWriterTokenWriter (writer), FormattingOptionsFactory.CreateMono ()); - return writer.ToString (); - } - - public void ConvertEntity (IEntity entity, TextWriterTokenWriter formatter, CSharpFormattingOptions formattingPolicy) - { - if (entity == null) - throw new ArgumentNullException ("entity"); - if (formatter == null) - throw new ArgumentNullException ("formatter"); - if (formattingPolicy == null) - throw new ArgumentNullException ("options"); - - TypeSystemAstBuilder astBuilder = CreateAstBuilder (); - EntityDeclaration node = astBuilder.ConvertEntity (entity); - PrintModifiers (node.Modifiers, formatter); - - if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyword) == ConversionFlags.ShowDefinitionKeyword) { - if (node is TypeDeclaration) { - switch (((TypeDeclaration)node).ClassType) { - case ClassType.Class: - formatter.WriteKeyword (Roles.ClassKeyword, "class"); - break; - case ClassType.Struct: - formatter.WriteKeyword (Roles.StructKeyword, "struct"); - break; - case ClassType.Interface: - formatter.WriteKeyword (Roles.InterfaceKeyword, "interface"); - break; - case ClassType.Enum: - formatter.WriteKeyword (Roles.EnumKeyword, "enum"); - break; - default: - throw new Exception ("Invalid value for ClassType"); - } - formatter.Space (); - } else if (node is DelegateDeclaration) { - formatter.WriteKeyword (Roles.DelegateKeyword, "delegate"); - formatter.Space (); - } else if (node is EventDeclaration) { - formatter.WriteKeyword (EventDeclaration.EventKeywordRole, "event"); - formatter.Space (); - } - } - - if ((ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) { - var rt = node.GetChildByRole (Roles.Type); - if (!rt.IsNull) { - rt.AcceptVisitor (new CSharpOutputVisitor (formatter, formattingPolicy)); - formatter.Space (); - } - } - - if (entity is ITypeDefinition) - WriteTypeDeclarationName ((ITypeDefinition)entity, formatter, formattingPolicy); - else - WriteMemberDeclarationName ((IMember)entity, formatter, formattingPolicy); - - if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList && HasParameters (entity)) { - if (entity.SymbolKind == SymbolKind.Indexer) - formatter.WriteToken (Roles.LBracket, "["); - else - formatter.WriteToken (Roles.LBrace, "("); - bool first = true; - foreach (var param in node.GetChildrenByRole(Roles.Parameter)) { - if (first) { - first = false; - } else { - formatter.WriteToken (Roles.Comma, ","); - formatter.Space (); - } - param.AcceptVisitor (new CSharpOutputVisitor (formatter, formattingPolicy)); - } - if (entity.SymbolKind == SymbolKind.Indexer) - formatter.WriteToken (Roles.RBracket, "]"); - else - formatter.WriteToken (Roles.RBrace, ")"); - } - - if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration)) { - IProperty property = entity as IProperty; - if (property != null) { - formatter.Space (); - formatter.WriteToken (Roles.LBrace, "{"); - formatter.Space (); - if (property.CanGet) { - formatter.WriteKeyword (PropertyDeclaration.GetKeywordRole, "get"); - formatter.WriteToken (Roles.Semicolon, ";"); - formatter.Space (); - } - if (property.CanSet) { - formatter.WriteKeyword (PropertyDeclaration.SetKeywordRole, "set"); - formatter.WriteToken (Roles.Semicolon, ";"); - formatter.Space (); - } - formatter.WriteToken (Roles.RBrace, "}"); - } else { - formatter.WriteToken (Roles.Semicolon, ";"); - } - } - } - - bool HasParameters (IEntity e) - { - switch (e.SymbolKind) { - case SymbolKind.TypeDefinition: - return ((ITypeDefinition)e).Kind == TypeKind.Delegate; - case SymbolKind.Indexer: - case SymbolKind.Method: - case SymbolKind.Operator: - case SymbolKind.Constructor: - case SymbolKind.Destructor: - return true; - default: - return false; - } - } - public string ConvertConstantValue (object constantValue) - { - if (constantValue == null) - return "null"; - return constantValue.ToString (); - } - - TypeSystemAstBuilder CreateAstBuilder () - { - return builder; - } - - void WriteTypeDeclarationName (ITypeDefinition typeDef, TextWriterTokenWriter formatter, CSharpFormattingOptions formattingPolicy) - { - TypeSystemAstBuilder astBuilder = CreateAstBuilder (); - if (typeDef.DeclaringTypeDefinition != null) { - WriteTypeDeclarationName (typeDef.DeclaringTypeDefinition, formatter, formattingPolicy); - formatter.WriteToken (Roles.Dot, "."); - } else if ((ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) == ConversionFlags.UseFullyQualifiedTypeNames) { - formatter.WriteIdentifier (Identifier.Create (typeDef.Namespace)); - formatter.WriteToken (Roles.Dot, "."); - } - formatter.WriteIdentifier (Identifier.Create (typeDef.Name)); - if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList) { - var outputVisitor = new CSharpOutputVisitor (formatter, formattingPolicy); - outputVisitor.WriteTypeParameters (astBuilder.ConvertEntity (typeDef).GetChildrenByRole (Roles.TypeParameter)); - } - } - - void WriteMemberDeclarationName (IMember member, TextWriterTokenWriter formatter, CSharpFormattingOptions formattingPolicy) - { - TypeSystemAstBuilder astBuilder = CreateAstBuilder (); - if ((ConversionFlags & ConversionFlags.ShowDeclaringType) == ConversionFlags.ShowDeclaringType) { - ConvertType (member.DeclaringType, formatter, formattingPolicy); - formatter.WriteToken (Roles.Dot, "."); - } - switch (member.SymbolKind) { - case SymbolKind.Indexer: - formatter.WriteKeyword (IndexerDeclaration.ThisKeywordRole, "this"); - break; - case SymbolKind.Constructor: - formatter.WriteIdentifier (Identifier.Create (member.DeclaringType.Name)); - break; - case SymbolKind.Destructor: - formatter.WriteToken (DestructorDeclaration.TildeRole, "~"); - formatter.WriteIdentifier (Identifier.Create (member.DeclaringType.Name)); - break; - case SymbolKind.Operator: - switch (member.Name) { - case "op_Implicit": - formatter.WriteKeyword (OperatorDeclaration.ImplicitRole, "implicit"); - formatter.Space (); - formatter.WriteKeyword (OperatorDeclaration.OperatorKeywordRole, "operator"); - formatter.Space (); - ConvertType (member.ReturnType, formatter, formattingPolicy); - break; - case "op_Explicit": - formatter.WriteKeyword (OperatorDeclaration.ExplicitRole, "explicit"); - formatter.Space (); - formatter.WriteKeyword (OperatorDeclaration.OperatorKeywordRole, "operator"); - formatter.Space (); - ConvertType (member.ReturnType, formatter, formattingPolicy); - break; - default: - formatter.WriteKeyword (OperatorDeclaration.OperatorKeywordRole, "operator"); - formatter.Space (); - var operatorType = OperatorDeclaration.GetOperatorType (member.Name); - if (operatorType.HasValue) { - formatter.WriteToken (OperatorDeclaration.GetRole (operatorType.Value), OperatorDeclaration.GetToken (operatorType.Value)); - } - else - formatter.WriteIdentifier (Identifier.Create (member.Name)); - break; - } - break; - default: - formatter.WriteIdentifier (Identifier.Create (member.Name)); - break; - } - if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList && member.SymbolKind == SymbolKind.Method) { - var outputVisitor = new CSharpOutputVisitor (formatter, formattingPolicy); - outputVisitor.WriteTypeParameters (astBuilder.ConvertEntity (member).GetChildrenByRole (Roles.TypeParameter)); - } - } - - void PrintModifiers (Modifiers modifiers, TextWriterTokenWriter formatter) - { - foreach (var m in CSharpModifierToken.AllModifiers) { - if ((modifiers & m) == m) { - formatter.WriteToken (TypeDeclaration.ModifierRole, CSharpModifierToken.GetModifierName (m)); - formatter.Space (); - } - } - } - - -#endregion - - public string ConvertVariable (IVariable v) - { - TypeSystemAstBuilder astBuilder = CreateAstBuilder (); - AstNode astNode = astBuilder.ConvertVariable (v); - return astNode.ToString ().TrimEnd (';', '\r', '\n'); - } - - public string ConvertType (IType type) - { - if (type == null) - throw new ArgumentNullException ("type"); - - TypeSystemAstBuilder astBuilder = CreateAstBuilder (); - AstType astType = astBuilder.ConvertType (type); - return astType.ToString (); - } - - public void ConvertType (IType type, TextWriterTokenWriter formatter, CSharpFormattingOptions formattingPolicy) - { - TypeSystemAstBuilder astBuilder = CreateAstBuilder (); - AstType astType = astBuilder.ConvertType (type); - astType.AcceptVisitor (new CSharpOutputVisitor (formatter, formattingPolicy)); - } - - public string WrapComment (string comment) - { - return "// " + comment; - } - } - - public static TooltipInformation CreateTooltipInformation (CSharpCompletionTextEditorExtension editorCompletion, CSharpResolver resolver, IEntity entity, bool smartWrap) - { - return CreateTooltipInformation (editorCompletion.UnresolvedFileCompilation, editorCompletion.CSharpUnresolvedFile, resolver, editorCompletion.TextEditorData, editorCompletion.FormattingPolicy, entity, smartWrap); - } - - public static TooltipInformation CreateTooltipInformation (ICompilation compilation, CSharpUnresolvedFile file, TextEditorData textEditorData, MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy formattingPolicy, IEntity entity, bool smartWrap, bool createFooter = false) - { - return CreateTooltipInformation (compilation, file, null, textEditorData, formattingPolicy, entity, smartWrap, createFooter); - } - - public static TooltipInformation CreateTooltipInformation (ICompilation compilation, CSharpUnresolvedFile file, CSharpResolver resolver, TextEditorData textEditorData, MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy formattingPolicy, IEntity entity, bool smartWrap, bool createFooter = false) - { - var tooltipInfo = new TooltipInformation (); - if (resolver == null) - resolver = file != null ? file.GetResolver (compilation, textEditorData.Caret.Location) : new CSharpResolver (compilation); - var sig = new SignatureMarkupCreator (resolver, formattingPolicy.CreateOptions ()); - sig.BreakLineAfterReturnType = smartWrap; - try { - tooltipInfo.SignatureMarkup = sig.GetMarkup (entity); - } catch (Exception e) { - LoggingService.LogError ("Got exception while creating markup for :" + entity, e); - return new TooltipInformation (); - } - tooltipInfo.SummaryMarkup = AmbienceService.GetSummaryMarkup (entity) ?? ""; - - if (entity is IMember) { - var evt = (IMember)entity; - if (evt.ReturnType.Kind == TypeKind.Delegate) { - tooltipInfo.AddCategory (GettextCatalog.GetString ("Delegate Info"), sig.GetDelegateInfo (evt.ReturnType)); - } - } - if (entity is IMethod) { - var method = (IMethod)entity; - if (method.IsExtensionMethod) { - tooltipInfo.AddCategory (GettextCatalog.GetString ("Extension Method from"), method.DeclaringTypeDefinition.FullName); - } - } - if (createFooter) { - tooltipInfo.FooterMarkup = sig.CreateFooter (entity); - } - return tooltipInfo; - } - - public static TooltipInformation CreateTooltipInformation (ICompilation compilation, CSharpUnresolvedFile file, TextEditorData textEditorData, MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy formattingPolicy, IType type, bool smartWrap, bool createFooter = false) - { - var tooltipInfo = new TooltipInformation (); - if (type.Kind == TypeKind.Unknown) - return tooltipInfo; - var resolver = file != null ? file.GetResolver (compilation, textEditorData.Caret.Location) : new CSharpResolver (compilation); - var sig = new SignatureMarkupCreator (resolver, formattingPolicy.CreateOptions ()); - sig.BreakLineAfterReturnType = smartWrap; - try { - tooltipInfo.SignatureMarkup = sig.GetMarkup (type.IsParameterized ? type.GetDefinition () : type); - } catch (Exception e) { - LoggingService.LogError ("Got exception while creating markup for :" + type, e); - return new TooltipInformation (); - } - if (type.IsParameterized) { - var typeInfo = new StringBuilder (); - for (int i = 0; i < type.TypeParameterCount; i++) { - typeInfo.AppendLine (type.GetDefinition ().TypeParameters [i].Name + " is " + sig.GetTypeReferenceString (type.TypeArguments [i])); - } - tooltipInfo.AddCategory ("Type Parameters", typeInfo.ToString ()); - } - - var def = type.GetDefinition (); - if (def != null) { - if (createFooter) - tooltipInfo.FooterMarkup = sig.CreateFooter (def); - tooltipInfo.SummaryMarkup = AmbienceService.GetSummaryMarkup (def) ?? ""; - } - return tooltipInfo; - } - - public override TooltipInformation CreateTooltipInformation (bool smartWrap) - { - return CreateTooltipInformation (compilation, file, editorCompletion.TextEditorData, editorCompletion.FormattingPolicy, Entity, smartWrap); - } - #region IOverloadedCompletionData implementation - - class OverloadSorter : IComparer<ICompletionData> - { - public OverloadSorter () - { - } - - public int Compare (ICompletionData x, ICompletionData y) - { - var mx = ((MemberCompletionData)x).Entity as IMember; - var my = ((MemberCompletionData)y).Entity as IMember; - int result; - - if (mx is ITypeDefinition && my is ITypeDefinition) { - result = ((((ITypeDefinition)mx).TypeParameters.Count).CompareTo (((ITypeDefinition)my).TypeParameters.Count)); - if (result != 0) - return result; - } - - if (mx is IMethod && my is IMethod) { - return MethodParameterDataProvider.MethodComparer ((IMethod)mx, (IMethod)my); - } - string sx = mx.ReflectionName;// ambience.GetString (mx, flags); - string sy = my.ReflectionName;// ambience.GetString (my, flags); - result = sx.Length.CompareTo (sy.Length); - return result == 0 ? string.Compare (sx, sy) : result; - } - } - - public override IEnumerable<ICompletionData> OverloadedData { - get { - if (overloads == null) - return new CompletionData[] { this }; - - var sorted = new List<ICompletionData> (overloads.Values); - sorted.Add (this); - sorted.Sort (new OverloadSorter ()); - return sorted; - } - } - - public override bool HasOverloads { - get { return overloads != null && overloads.Count > 0; } - } - - public override void AddOverload (ICSharpCode.NRefactory.Completion.ICompletionData data) - { - AddOverload ((MemberCompletionData)data); - } - - public void AddOverload (MemberCompletionData overload) - { - if (overloads == null) - overloads = new Dictionary<string, CompletionData> (); - - if (overload.Entity is IMember && Entity is IMember) { - // filter overriden members that came from base classes - // note that the overload tree is traversed top down. - var member = Entity as IMember; - if (member.IsOverride) - return; - - string MemberId = (overload.Entity as IMember).GetIdString (); - if (MemberId != (this.Entity as IMember).GetIdString () && !overloads.ContainsKey (MemberId)) { - overloads [MemberId] = overload; - - //if any of the overloads is obsolete, we should not mark the item obsolete - if (!(overload.Entity as IMember).IsObsolete ()) - DisplayFlags &= ~DisplayFlags.Obsolete; - } - } - } - #endregion - - #region IEntityCompletionData implementation - public IEntity Entity { - get; - set; - } - #endregion - - public override int CompareTo (object obj) - { - int result = base.CompareTo (obj); - if (result == 0) { - var mcd = obj as MemberCompletionData; - if (mcd != null) { - var mc = mcd; - if (this.Entity.SymbolKind == SymbolKind.Method) { - var method = (IMethod)this.Entity; - if (method.IsExtensionMethod) - return 1; - } - if (mc.Entity.SymbolKind == SymbolKind.Method) { - var method = (IMethod)mc.Entity; - if (method.IsExtensionMethod) - return -1; - } - } else { - return -1; - } - } - return result; - } - - public override string ToString () - { - return string.Format ("[MemberCompletionData: Entity={0}]", Entity); - } - } -} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MethodParameterDataProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MethodParameterDataProvider.cs index 01551b3b39..d9114e5050 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MethodParameterDataProvider.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MethodParameterDataProvider.cs @@ -39,7 +39,7 @@ using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.CSharp.Completion; using MonoDevelop.Ide.CodeCompletion; -using Mono.TextEditor; +using MonoDevelop.Ide.Editor; namespace MonoDevelop.CSharp.Completion { @@ -126,55 +126,55 @@ namespace MonoDevelop.CSharp.Completion public static TooltipInformation CreateTooltipInformation (CSharpCompletionTextEditorExtension ext, ICompilation compilation, CSharpUnresolvedFile file, IParameterizedMember entity, int currentParameter, bool smartWrap) { - return CreateTooltipInformation (compilation, file, ext.TextEditorData, ext.FormattingPolicy, entity, currentParameter, smartWrap); + return CreateTooltipInformation (compilation, file, ext.Editor, ext.FormattingPolicy, entity, currentParameter, smartWrap); } - public static TooltipInformation CreateTooltipInformation (ICompilation compilation, CSharpUnresolvedFile file, TextEditorData textEditorData, MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy formattingPolicy, IParameterizedMember entity, int currentParameter, bool smartWrap) + public static TooltipInformation CreateTooltipInformation (ICompilation compilation, CSharpUnresolvedFile file, TextEditor textEditorData, MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy formattingPolicy, IParameterizedMember entity, int currentParameter, bool smartWrap) { var tooltipInfo = new TooltipInformation (); - var resolver = file.GetResolver (compilation, textEditorData.Caret.Location); - var sig = new SignatureMarkupCreator (resolver, formattingPolicy.CreateOptions ()); - sig.HighlightParameter = currentParameter; - sig.BreakLineAfterReturnType = smartWrap; - try { - tooltipInfo.SignatureMarkup = sig.GetMarkup (entity); - } catch (Exception e) { - LoggingService.LogError ("Got exception while creating markup for :" + entity, e); - return new TooltipInformation (); - } - tooltipInfo.SummaryMarkup = AmbienceService.GetSummaryMarkup (entity) ?? ""; - - if (entity is IMethod) { - var method = (IMethod)entity; - if (method.IsExtensionMethod) { - tooltipInfo.AddCategory (GettextCatalog.GetString ("Extension Method from"), method.DeclaringTypeDefinition.FullName); - } - } - int paramIndex = currentParameter; - - if (entity is IMethod && ((IMethod)entity).IsExtensionMethod) - paramIndex++; - paramIndex = Math.Min (entity.Parameters.Count - 1, paramIndex); - - var curParameter = paramIndex >= 0 && paramIndex < entity.Parameters.Count ? entity.Parameters [paramIndex] : null; - if (curParameter != null) { - - string docText = AmbienceService.GetDocumentation (entity); - if (!string.IsNullOrEmpty (docText)) { - string text = docText; - Regex paramRegex = new Regex ("(\\<param\\s+name\\s*=\\s*\"" + curParameter.Name + "\"\\s*\\>.*?\\</param\\>)", RegexOptions.Compiled); - Match match = paramRegex.Match (docText); - - if (match.Success) { - text = AmbienceService.GetDocumentationMarkup (entity, match.Groups [1].Value); - if (!string.IsNullOrWhiteSpace (text)) - tooltipInfo.AddCategory (GettextCatalog.GetString ("Parameter"), text); - } - } - - if (curParameter.Type.Kind == TypeKind.Delegate) - tooltipInfo.AddCategory (GettextCatalog.GetString ("Delegate Info"), sig.GetDelegateInfo (curParameter.Type)); - } +// var resolver = file.GetResolver (compilation, textEditorData.Caret.Location); +// var sig = new SignatureMarkupCreator (resolver, formattingPolicy.CreateOptions ()); +// sig.HighlightParameter = currentParameter; +// sig.BreakLineAfterReturnType = smartWrap; +// try { +// tooltipInfo.SignatureMarkup = sig.GetMarkup (entity); +// } catch (Exception e) { +// LoggingService.LogError ("Got exception while creating markup for :" + entity, e); +// return new TooltipInformation (); +// } +// tooltipInfo.SummaryMarkup = AmbienceService.GetSummaryMarkup (entity) ?? ""; +// +// if (entity is IMethod) { +// var method = (IMethod)entity; +// if (method.IsExtensionMethod) { +// tooltipInfo.AddCategory (GettextCatalog.GetString ("Extension Method from"), method.DeclaringTypeDefinition.FullName); +// } +// } +// int paramIndex = currentParameter; +// +// if (entity is IMethod && ((IMethod)entity).IsExtensionMethod) +// paramIndex++; +// paramIndex = Math.Min (entity.Parameters.Count - 1, paramIndex); +// +// var curParameter = paramIndex >= 0 && paramIndex < entity.Parameters.Count ? entity.Parameters [paramIndex] : null; +// if (curParameter != null) { +// +// string docText = AmbienceService.GetDocumentation (entity); +// if (!string.IsNullOrEmpty (docText)) { +// string text = docText; +// Regex paramRegex = new Regex ("(\\<param\\s+name\\s*=\\s*\"" + curParameter.Name + "\"\\s*\\>.*?\\</param\\>)", RegexOptions.Compiled); +// Match match = paramRegex.Match (docText); +// +// if (match.Success) { +// text = AmbienceService.GetDocumentationMarkup (entity, match.Groups [1].Value); +// if (!string.IsNullOrWhiteSpace (text)) +// tooltipInfo.AddCategory (GettextCatalog.GetString ("Parameter"), text); +// } +// } +// +// if (curParameter.Type.Kind == TypeKind.Delegate) +// tooltipInfo.AddCategory (GettextCatalog.GetString ("Delegate Info"), sig.GetDelegateInfo (curParameter.Type)); +// } return tooltipInfo; } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MonoCSharpCompletionEngine.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MonoCSharpCompletionEngine.cs deleted file mode 100644 index 0046a7322d..0000000000 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MonoCSharpCompletionEngine.cs +++ /dev/null @@ -1,104 +0,0 @@ -// -// MonoCSharpCompletionEngine.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using ICSharpCode.NRefactory.CSharp.Completion; -using System.Collections.Generic; -using MonoDevelop.CodeGeneration; -using ICSharpCode.NRefactory.TypeSystem; -using System.Linq; -using MonoDevelop.CSharp.Refactoring.CodeActions; -using ICSharpCode.NRefactory.Editor; - -namespace MonoDevelop.CSharp.Completion -{ - class MonoCSharpCompletionEngine : CSharpCompletionEngine - { - readonly CSharpCompletionTextEditorExtension ext; - - public CSharpCompletionTextEditorExtension Ext { - get { - return ext; - } - } - - public MDRefactoringContext MDRefactoringCtx { - get { - return ext.MDRefactoringCtx; - } - } - - public MonoCSharpCompletionEngine (CSharpCompletionTextEditorExtension ext, ICSharpCode.NRefactory.Editor.IDocument document, ICompletionContextProvider completionContextProvider, ICompletionDataFactory factory, ICSharpCode.NRefactory.TypeSystem.IProjectContent content, ICSharpCode.NRefactory.CSharp.TypeSystem.CSharpTypeResolveContext ctx) : base (document, completionContextProvider, factory, content, ctx) - { - this.ext = ext; - } - - protected override void AddVirtuals (List<IMember> alreadyInserted, CompletionDataWrapper col, string modifiers, IType curType, int declarationBegin) - { - base.AddVirtuals (alreadyInserted, col, modifiers, curType, declarationBegin); - foreach (var member in GetProtocolMembers (curType)) { - if (alreadyInserted.Contains (member)) - continue; - if (BaseExportCodeGenerator.IsImplemented (curType, member)) - continue; - alreadyInserted.Add (member); - var data = new ProtocolCompletionData (this, declarationBegin, member); - col.Add (data); - } - } - - internal static bool IsFoundationNamespace (string ns ) - { - return (ns == "MonoTouch.Foundation" || ns == "Foundation"); - } - - IEnumerable<IMember> GetProtocolMembers (IType curType) - { - foreach (var t in curType.DirectBaseTypes) { - string name; - if (!BaseExportCodeGenerator.HasProtocolAttribute (t, out name)) - continue; - var protocolType = Compilation.FindType (new FullTypeName (new TopLevelTypeName (t.Namespace, name))); - if (protocolType == null) - break; - foreach (var member in protocolType.GetMethods (null, GetMemberOptions.IgnoreInheritedMembers)) { - if (member.ImplementedInterfaceMembers.Any () || member.IsAbstract || !member.IsVirtual) - continue; - if (member.Attributes.Any (a => a.AttributeType.Name == "ExportAttribute" && IsFoundationNamespace (a.AttributeType.Namespace))) { - yield return member; - } - } - foreach (var member in protocolType.GetProperties (null, GetMemberOptions.IgnoreInheritedMembers)) { - if (member.ImplementedInterfaceMembers.Any () || member.IsAbstract || !member.IsVirtual) - continue; - if (member.CanGet && member.Getter.Attributes.Any (a => a.AttributeType.Name == "ExportAttribute" && IsFoundationNamespace (a.AttributeType.Namespace)) || - member.CanSet && member.Setter.Attributes.Any (a => a.AttributeType.Name == "ExportAttribute" && IsFoundationNamespace (a.AttributeType.Namespace))) - yield return member; - } - } - } - } -} - diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ObjectCreationCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ObjectCreationCompletionData.cs new file mode 100644 index 0000000000..47a52cadc8 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ObjectCreationCompletionData.cs @@ -0,0 +1,150 @@ +// +// CSharpCompletionTextEditorExtension.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2011 Xamarin <http://xamarin.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Microsoft.CodeAnalysis; +using MonoDevelop.Ide.CodeCompletion; +using System.Text; +using MonoDevelop.Ide.TypeSystem; +using MonoDevelop.Ide.Editor.Extension; +using System.Linq; +using Gtk; +using MonoDevelop.Ide; +using System.Collections.Generic; + +namespace MonoDevelop.CSharp.Completion +{ + class ObjectCreationCompletionData : RoslynSymbolCompletionData + { + public static readonly SymbolDisplayFormat HideParameters = + new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, + propertyStyle: SymbolDisplayPropertyStyle.NameOnly, + genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, + memberOptions: SymbolDisplayMemberOptions.None, + parameterOptions: + SymbolDisplayParameterOptions.None, + miscellaneousOptions: + SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | + SymbolDisplayMiscellaneousOptions.UseSpecialTypes + ); + + readonly ITypeSymbol type; + readonly ISymbol symbol; + ISymbol insertSymbol; + readonly int declarationBegin; + readonly bool afterKeyword; + readonly SemanticModel semanticModel; + + string displayText; + + + public override string DisplayText { + get { + if (displayText == null) { + displayText = CropGlobal(symbol.ToMinimalDisplayString (semanticModel, declarationBegin, Ambience.LabelFormat)) + "()"; + if (!afterKeyword) + displayText = "new " + displayText; + } + return displayText; + } + } + + public override string GetDisplayTextMarkup () + { + var model = ext.ParsedDocument.GetAst<SemanticModel> (); + + var result = "<b>" + Ambience.EscapeText (CropGlobal(symbol.ToMinimalDisplayString (model, declarationBegin, HideParameters))) + "</b>()"; + if (!afterKeyword) + result = "new " + result; + return ApplyDiplayFlagsFormatting (result); + } + + static string CropGlobal (string str) + { + // shouldn't happen according to the display format - but happens. bug ? + if (str.StartsWith ("global::")) + return str.Substring ("global::".Length); + return str; + } + + public override bool HasOverloads { + get { + return true; + } + } + + List<CompletionData> overloads; + public override IReadOnlyList<CompletionData> OverloadedData { + get { + if (overloads == null) { + overloads = new List<CompletionData> (); + foreach (var constructor in type.GetMembers ().OfType<IMethodSymbol> ().Where (m => m.MethodKind == MethodKind.Constructor)) { + overloads.Add (new ObjectCreationCompletionData (keyHandler, ext, semanticModel, type, constructor, declarationBegin, afterKeyword) { insertSymbol = this.insertSymbol }); + } + } + return overloads; + } + } + + public ObjectCreationCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, CSharpCompletionTextEditorExtension ext, SemanticModel semanticModel, ITypeSymbol type, ISymbol symbol, int declarationBegin, bool afterKeyword) : base(keyHandler, ext, symbol) + { + this.type = type; + this.semanticModel = semanticModel; + this.afterKeyword = afterKeyword; + this.declarationBegin = declarationBegin; + this.symbol = insertSymbol = symbol; + } + + protected override string GetInsertionText () + { + var sb = new StringBuilder (); + if (!afterKeyword) + sb.Append ("new "); + sb.Append (CropGlobal (insertSymbol.ToMinimalDisplayString (semanticModel, declarationBegin, HideParameters))); + return sb.ToString () ; + } + + public override int CompareTo (object obj) + { + var objCrCompData = obj as ObjectCreationCompletionData; + if (objCrCompData == null) + return -1; + + return DisplayText.CompareTo(objCrCompData.DisplayText); + } + + internal static bool HasAnyConstructorWithParameters (ITypeSymbol symbol) + { + return symbol.GetMembers() + .OfType<IMethodSymbol>() + .Where(m => m.MethodKind == MethodKind.Constructor) + .Any (m => m.Parameters.Length > 0); + } + } + +} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ProtocolCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ProtocolCompletionData.cs index edb8a32224..ee382e0f99 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ProtocolCompletionData.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ProtocolCompletionData.cs @@ -28,60 +28,120 @@ using ICSharpCode.NRefactory.TypeSystem; using MonoDevelop.Ide.CodeCompletion; using MonoDevelop.Ide.TypeSystem; using MonoDevelop.CodeGeneration; +using MonoDevelop.Ide.Editor.Extension; +using Microsoft.CodeAnalysis; +using MonoDevelop.CSharp.Refactoring; +using System.Linq; +using MonoDevelop.CSharp.Formatting; namespace MonoDevelop.CSharp.Completion { - class ProtocolCompletionData : CompletionData + class ProtocolCompletionData : RoslynSymbolCompletionData { - readonly MonoCSharpCompletionEngine engine; - readonly IMember member; - readonly static Ambience ambience = new CSharpAmbience (); - readonly int declarationBegin; + readonly int declarationBegin; + readonly ITypeSymbol currentType; public bool GenerateBody { get; set; } - public override TooltipInformation CreateTooltipInformation (bool smartWrap) - { - return MemberCompletionData.CreateTooltipInformation (engine.Ext, null, member, smartWrap); + static readonly SymbolDisplayFormat NameFormat = + new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, + propertyStyle: SymbolDisplayPropertyStyle.NameOnly, + genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance, + memberOptions: SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeExplicitInterface, + parameterOptions: + SymbolDisplayParameterOptions.IncludeParamsRefOut | + SymbolDisplayParameterOptions.IncludeExtensionThis | + SymbolDisplayParameterOptions.IncludeType | + SymbolDisplayParameterOptions.IncludeName, + miscellaneousOptions: + SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | + SymbolDisplayMiscellaneousOptions.UseSpecialTypes); + + internal static readonly SymbolDisplayFormat overrideNameFormat = NameFormat.WithParameterOptions( + SymbolDisplayParameterOptions.IncludeDefaultValue | + SymbolDisplayParameterOptions.IncludeExtensionThis | + SymbolDisplayParameterOptions.IncludeType | + SymbolDisplayParameterOptions.IncludeName | + SymbolDisplayParameterOptions.IncludeParamsRefOut); + + string displayText; + + bool afterKeyword; + + public override string DisplayText { + get { + if (displayText == null) { + var model = ext.ParsedDocument.GetAst<SemanticModel> (); + displayText = base.Symbol.ToMinimalDisplayString (model, ext.Editor.CaretOffset, overrideNameFormat); + if (!afterKeyword) + displayText = "override " + displayText; + } + + return displayText; + } } - public ProtocolCompletionData (MonoCSharpCompletionEngine engine, int declarationBegin, IMember member) : base (null) - { - this.engine = engine; - this.member = member; + public ProtocolCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, CSharpCompletionTextEditorExtension ext, int declarationBegin, ITypeSymbol currentType, Microsoft.CodeAnalysis.ISymbol member, bool afterKeyword) : base (keyHandler, ext, member, member.ToDisplayString ()) + { + this.afterKeyword = afterKeyword; + this.currentType = currentType; this.declarationBegin = declarationBegin; this.GenerateBody = true; - this.Icon = member.GetStockIcon (); - this.DisplayText = ambience.GetString (member, OutputFlags.IncludeParameters | OutputFlags.IncludeParameterName | OutputFlags.IncludeGenerics | OutputFlags.HideExtensionsParameter| OutputFlags.IncludeAccessor); - this.CompletionText = member.SymbolKind == SymbolKind.Indexer ? "this" : member.Name; } - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, KeyDescriptor descriptor) { - var ext = engine.Ext; - var editor = ext.TextEditorData; - var generator = CodeGenerator.CreateGenerator (ext.Document); - if (ext.Project != null) - generator.PolicyParent = ext.Project.Policies; - var builder = engine.MDRefactoringCtx.CreateTypeSystemAstBuilder (); - - string sb = BaseExportCodeGenerator.GenerateMemberCode (engine.MDRefactoringCtx, builder, member); + var editor = ext.Editor; + bool isExplicit = false; + // if (member.DeclaringTypeDefinition.Kind == TypeKind.Interface) { + // foreach (var m in type.Members) { + // if (m.Name == member.Name && !m.ReturnType.Equals (member.ReturnType)) { + // isExplicit = true; + // break; + // } + // } + // } + // var resolvedType = type.Resolve (ext.Project).GetDefinition (); + // if (ext.Project != null) + // generator.PolicyParent = ext.Project.Policies; + + var result = CSharpCodeGenerator.CreateProtocolMemberImplementation (ext.DocumentContext, ext.Editor, currentType, currentType.Locations.First (), Symbol, isExplicit); + string sb = result.Code.TrimStart (); + int trimStart = result.Code.Length - sb.Length; sb = sb.TrimEnd (); - string indent = editor.GetIndentationString (editor.Caret.Location); - sb = sb.Replace (editor.EolMarker, editor.EolMarker + indent); + var lastRegion = result.BodyRegions.LastOrDefault (); + var region = lastRegion == null? null + : new CodeGeneratorBodyRegion (lastRegion.StartOffset - trimStart, lastRegion.EndOffset - trimStart); - int targetCaretPosition = sb.LastIndexOf ("throw", StringComparison.Ordinal); - int selectionEndPosition = sb.LastIndexOf (";", StringComparison.Ordinal); + int targetCaretPosition; + int selectionEndPosition = -1; + if (region != null && region.IsValid) { + targetCaretPosition = declarationBegin + region.StartOffset; + if (region.Length > 0) { + if (GenerateBody) { + selectionEndPosition = declarationBegin + region.EndOffset; + } else { + //FIXME: if there are multiple regions, remove all of them + sb = sb.Substring (0, region.StartOffset) + sb.Substring (region.EndOffset); + } + } + } else { + targetCaretPosition = declarationBegin + sb.Length; + } - editor.Replace (declarationBegin, editor.Caret.Offset - declarationBegin, sb); + editor.ReplaceText (declarationBegin, editor.CaretOffset - declarationBegin, sb); if (selectionEndPosition > 0) { - targetCaretPosition += declarationBegin; - selectionEndPosition += declarationBegin; - editor.Caret.Offset = selectionEndPosition; + editor.CaretOffset = selectionEndPosition; editor.SetSelection (targetCaretPosition, selectionEndPosition); + } else { + editor.CaretOffset = targetCaretPosition; } + + OnTheFlyFormatter.Format (editor, ext.DocumentContext, declarationBegin, declarationBegin + sb.Length); } } } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ProtocolMemberContextHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ProtocolMemberContextHandler.cs new file mode 100644 index 0000000000..5aa77d4301 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/ProtocolMemberContextHandler.cs @@ -0,0 +1,153 @@ +// +// ProtocolMemberContextHandler.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory6.CSharp.Completion; +using System.Collections.Generic; +using ICSharpCode.NRefactory6.CSharp; +using Microsoft.CodeAnalysis; +using System.Threading; +using System.Linq; +using Mono.Addins.Description; + +namespace MonoDevelop.CSharp.Completion +{ + class ProtocolMemberContextHandler : OverrideContextHandler + { + CSharpCompletionTextEditorExtension extension; + + public ProtocolMemberContextHandler (CSharpCompletionTextEditorExtension extension) + { + this.extension = extension; + } + + protected override IEnumerable<ICompletionData> CreateCompletionData (CompletionEngine engine, SemanticModel semanticModel, int position, ITypeSymbol returnType, Accessibility seenAccessibility, SyntaxToken startToken, SyntaxToken tokenBeforeReturnType, bool afterKeyword, CancellationToken cancellationToken) + { + var result = new List<ICompletionData> (); + ISet<ISymbol> overridableMembers; + if (!TryDetermineOverridableMembers (semanticModel, tokenBeforeReturnType, seenAccessibility, out overridableMembers, cancellationToken)) { + return result; + } + if (returnType != null) { + overridableMembers = FilterOverrides (overridableMembers, returnType); + } + var curType = semanticModel.GetEnclosingSymbol<INamedTypeSymbol> (startToken.SpanStart, cancellationToken); + var declarationBegin = afterKeyword ? startToken.SpanStart : position; + foreach (var m in overridableMembers) { + var data = new ProtocolCompletionData (this, extension, declarationBegin, curType, m, afterKeyword); + result.Add (data); + } + return result; + } + + static bool TryDetermineOverridableMembers(SemanticModel semanticModel, SyntaxToken startToken, Accessibility seenAccessibility, out ISet<ISymbol> overridableMembers, CancellationToken cancellationToken) + { + var result = new HashSet<ISymbol>(); + var containingType = semanticModel.GetEnclosingSymbol<INamedTypeSymbol>(startToken.SpanStart, cancellationToken); + if (containingType != null && !containingType.IsScriptClass && !containingType.IsImplicitClass) + { + if (containingType.TypeKind == TypeKind.Class || containingType.TypeKind == TypeKind.Struct) + { + var baseTypes = containingType.GetBaseTypes().Reverse(); + foreach (var type in baseTypes) + { + cancellationToken.ThrowIfCancellationRequested(); + + // Prefer overrides in derived classes + RemoveOverriddenMembers(result, type, cancellationToken); + + // Retain overridable methods + AddProtocolMembers(semanticModel, result, containingType, type, cancellationToken); + } + // Don't suggest already overridden members + RemoveOverriddenMembers(result, containingType, cancellationToken); + } + } + + // Filter based on accessibility + if (seenAccessibility != Accessibility.NotApplicable) + { + result.RemoveWhere(m => m.DeclaredAccessibility != seenAccessibility); + } + + overridableMembers = result; + return overridableMembers.Count > 0; + } + + static void AddProtocolMembers(SemanticModel semanticModel, HashSet<ISymbol> result, INamedTypeSymbol containingType, INamedTypeSymbol type, CancellationToken cancellationToken) + { + string name; + if (!HasProtocolAttribute (containingType, out name)) + return; + + var protocolType = semanticModel.Compilation.GetTypeByMetadataName (name); + if (protocolType == null) + return; + + foreach (var member in protocolType.GetMembers ().OfType<IMethodSymbol> ()) { + if (member.ExplicitInterfaceImplementations.Length > 0 || member.IsAbstract || !member.IsVirtual) + continue; + if (member.GetAttributes ().Any (a => a.AttributeClass.Name == "ExportAttribute" && IsFoundationNamespace (a.AttributeClass.ContainingNamespace.GetFullName ()))) { + result.Add (member); + } + + } + foreach (var member in protocolType.GetMembers ().OfType<IPropertySymbol> ()) { + if (member.ExplicitInterfaceImplementations.Length > 0 || member.IsAbstract || !member.IsVirtual) + continue; + if (member.GetMethod != null && member.GetMethod.GetAttributes ().Any (a => a.AttributeClass.Name == "ExportAttribute" && IsFoundationNamespace (a.AttributeClass.ContainingNamespace.GetFullName ())) || + member.SetMethod != null && member.SetMethod.GetAttributes ().Any (a => a.AttributeClass.Name == "ExportAttribute" && IsFoundationNamespace (a.AttributeClass.ContainingNamespace.GetFullName ()))) + result.Add (member); + } + } + + internal static bool IsFoundationNamespace (string ns ) + { + return (ns == "MonoTouch.Foundation" || ns == "Foundation"); + } + + internal static bool IsFoundationNamespace (INamespaceSymbol ns) + { + return IsFoundationNamespace (ns.GetFullName ()); + } + + internal static bool HasProtocolAttribute (INamedTypeSymbol type, out string name) + { + foreach (var attrs in type.GetAttributes ()) { + if (attrs.AttributeClass.Name == "ProtocolAttribute" && IsFoundationNamespace (attrs.AttributeClass.ContainingNamespace.GetFullName ())) { + foreach (var na in attrs.NamedArguments) { + if (na.Key != "Name") + continue; + name = na.Value.Value as string; + if (name != null) + return true; + } + } + } + name = null; + return false; + } + } +}
\ No newline at end of file diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCodeCompletionFactory.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCodeCompletionFactory.cs new file mode 100644 index 0000000000..9dded644c7 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCodeCompletionFactory.cs @@ -0,0 +1,221 @@ +// +// CSharpCompletionTextEditorExtension.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2011 Xamarin <http://xamarin.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Microsoft.CodeAnalysis; +using MonoDevelop.Core; +using MonoDevelop.Ide.CodeCompletion; +using System.Collections.Generic; +using System.Linq; +using MonoDevelop.Ide.TypeSystem; + +namespace MonoDevelop.CSharp.Completion +{ + class RoslynCodeCompletionFactory : ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory + { + readonly CSharpCompletionTextEditorExtension ext; + readonly SemanticModel semanticModel; + + public RoslynCodeCompletionFactory (CSharpCompletionTextEditorExtension ext, SemanticModel semanticModel) + { + if (ext == null) + throw new ArgumentNullException ("ext"); + if (semanticModel == null) + throw new ArgumentNullException ("semanticModel"); + this.semanticModel = semanticModel; + this.ext = ext; + } + + #region ICompletionDataFactory implementation + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateGenericData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string data, ICSharpCode.NRefactory6.CSharp.Completion.GenericDataType genericDataType) + { + return new RoslynCompletionData (keyHandler) { + CompletionText = data, + DisplayText = data, + Icon = "md-keyword" + }; + } + + ICSharpCode.NRefactory6.CSharp.Completion.ISymbolCompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateEnumMemberCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, ISymbol alias, IFieldSymbol field) + { + var model = ext.ParsedDocument.GetAst<SemanticModel> (); + return new RoslynSymbolCompletionData (keyHandler, ext, field, (alias ?? field.Type).ToMinimalDisplayString (model, ext.Editor.CaretOffset, Ambience.NameFormat) + "." + field.Name); + } + + class FormatItemCompletionData : RoslynCompletionData + { + string format; + string description; + object example; + + public FormatItemCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string format, string description, object example) : base (keyHandler) + { + this.format = format; + this.description = description; + this.example = example; + } + + public override string DisplayText { + get { + return format; + } + } + + public override string GetDisplayDescription (bool isSelected) + { + return "- <span foreground=\"darkgray\" size='small'>" + description + "</span>"; + } + + string rightSideDescription = null; + public override string GetRightSideDescription (bool isSelected) + { + if (rightSideDescription == null) { + try { + rightSideDescription = "<span size='small'>" + string.Format ("{0:" +format +"}", example) +"</span>"; + } catch (Exception e) { + rightSideDescription = ""; + LoggingService.LogError ("Format error.", e); + } + } + return rightSideDescription; + } + + public override string CompletionText { + get { + return format; + } + } + + public override int CompareTo (object obj) + { + return 0; + } + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateFormatItemCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string format, string description, object example) + { + return new FormatItemCompletionData (keyHandler, format, description, example); + } + + class XmlDocCompletionData : RoslynCompletionData + { + //readonly CSharpCompletionTextEditorExtension ext; + readonly string title; + /* + #region IListData implementation + + CSharpCompletionDataList list; + public CSharpCompletionDataList List { + get { + return list; + } + set { + list = value; + } + } + + #endregion*/ + + public XmlDocCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, CSharpCompletionTextEditorExtension ext, string title, string description, string insertText) : base (keyHandler, title, "md-keyword", description, insertText ?? title) + { + // this.ext = ext; + this.title = title; + } +// public override TooltipInformation CreateTooltipInformation (bool smartWrap) +// { +// var sig = new SignatureMarkupCreator (ext.Editor, ext.DocumentContext, ext.Editor.CaretOffset); +// sig.BreakLineAfterReturnType = smartWrap; +// return sig.GetKeywordTooltip (title, null); +// } + + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, MonoDevelop.Ide.Editor.Extension.KeyDescriptor descriptor) + { + var currentWord = GetCurrentWord (window); + var text = CompletionText; + if (descriptor.KeyChar != '>') + text += ">"; + window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, currentWord, text); + } + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateXmlDocCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string title, string description, string insertText) + { + return new XmlDocCompletionData (keyHandler, ext, title, description, insertText); + } + + ICSharpCode.NRefactory6.CSharp.Completion.ISymbolCompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateSymbolCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, ISymbol symbol) + { + return new RoslynSymbolCompletionData (keyHandler, ext, symbol, symbol.Name); + } + + ICSharpCode.NRefactory6.CSharp.Completion.ISymbolCompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateSymbolCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, ISymbol symbol, string text) + { + return new RoslynSymbolCompletionData (keyHandler, ext, symbol, text); + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateNewOverrideCompletionData(ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, int declarationBegin, ITypeSymbol currentType, ISymbol m, bool afterKeyword) + { + return new CreateOverrideCompletionData (keyHandler, ext, declarationBegin, currentType, m, afterKeyword); + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreatePartialCompletionData(ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, int declarationBegin, ITypeSymbol currentType, IMethodSymbol method, bool afterKeyword) + { + return new CreatePartialCompletionData (keyHandler, ext, declarationBegin, currentType, method, afterKeyword); + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateAnonymousMethod(ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string displayText, string description, string textBeforeCaret, string textAfterCaret) + { + return new AnonymousMethodCompletionData (keyHandler) { + CompletionText = textBeforeCaret + "|" + textAfterCaret, + DisplayText = displayText, + Description = description + }; + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateNewMethodDelegate(ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, ITypeSymbol delegateType, string varName, INamedTypeSymbol curType) + { + return new EventCreationCompletionData (keyHandler, ext, delegateType, varName, curType); + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateObjectCreation (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, ITypeSymbol type, ISymbol symbol, int declarationBegin, bool afterKeyword) + { + return new ObjectCreationCompletionData (keyHandler, ext, semanticModel, type, symbol, declarationBegin, afterKeyword); + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateCastCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, ISymbol member, SyntaxNode nodeToCast, ITypeSymbol targetType) + { + return new CastCompletionData (keyHandler, ext, semanticModel, member, nodeToCast, targetType); + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionCategory ICSharpCode.NRefactory6.CSharp.Completion.ICompletionDataFactory.CreateCompletionDataCategory (ISymbol forSymbol) + { + return new RoslynCompletionCategory (forSymbol); + } + + #endregion + } +} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/VariableCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCompletionCategory.cs index 34ae8a585a..b3edbdff03 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/VariableCompletionData.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCompletionCategory.cs @@ -1,21 +1,21 @@ -// -// VariableCompletionData.cs -// +// +// RoslynCompletionCategory.cs +// // Author: // Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com) -// +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -25,35 +25,38 @@ // THE SOFTWARE. using System; using MonoDevelop.Ide.CodeCompletion; -using ICSharpCode.NRefactory.Completion; -using ICSharpCode.NRefactory.TypeSystem; +using Microsoft.CodeAnalysis; using MonoDevelop.Ide.TypeSystem; +using ICSharpCode.NRefactory6.CSharp; +using System.Linq; namespace MonoDevelop.CSharp.Completion { - class VariableCompletionData : CompletionData, IVariableCompletionData + class RoslynCompletionCategory : CompletionCategory, ICSharpCode.NRefactory6.CSharp.Completion.ICompletionCategory { - readonly CSharpCompletionTextEditorExtension ext; + readonly ISymbol symbol; - public IVariable Variable { - get; - private set; - } - - public override TooltipInformation CreateTooltipInformation (bool smartWrap) + public RoslynCompletionCategory (ISymbol symbol) { - var tooltipInfo = new TooltipInformation (); - var resolver = ext.CSharpUnresolvedFile.GetResolver (ext.Compilation, ext.Document.Editor.Caret.Location); - var sig = new SignatureMarkupCreator (resolver, ext.FormattingPolicy.CreateOptions ()); - sig.BreakLineAfterReturnType = smartWrap; - tooltipInfo.SignatureMarkup = sig.GetLocalVariableMarkup (Variable); - return tooltipInfo; + this.symbol = symbol; + this.DisplayText = symbol.ToDisplayString (Ambience.NameFormat); + this.Icon = symbol.GetStockIcon (); } - public VariableCompletionData (CSharpCompletionTextEditorExtension ext, IVariable variable) : base (variable.Name, variable.GetStockIcon ()) + public override int CompareTo (CompletionCategory other) { - this.ext = ext; - this.Variable = variable; + if (other == null) + return 1; + var t1 = symbol as INamedTypeSymbol; + var t2 = ((RoslynCompletionCategory)other).symbol as INamedTypeSymbol; + if (t1 != null && t2 != null) { + if (t1.AllInterfaces.Contains (t2) || t1.GetBaseTypes().Contains (t2)) + return -1; + if (t2.AllInterfaces.Contains (t1) || t2.GetBaseTypes().Contains (t1)) + return 1; + } + + return this.DisplayText.CompareTo (other.DisplayText); } } } diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCompletionData.cs new file mode 100644 index 0000000000..372e2e0ad7 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynCompletionData.cs @@ -0,0 +1,162 @@ +// +// RoslynCompletionData.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using MonoDevelop.Ide.CodeCompletion; +using Microsoft.CodeAnalysis; +using GLib; +using System.Collections.Generic; +using MonoDevelop.Core; +using MonoDevelop.Ide.TypeSystem; +using MonoDevelop.Ide.Editor.Extension; +using Xwt; +using MonoDevelop.Ide; + +namespace MonoDevelop.CSharp.Completion +{ + class RoslynCompletionData : CompletionData, ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData + { + List<CompletionData> overloads; + + public override bool HasOverloads { + get { + return overloads != null; + } + } + + void ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData.AddOverload (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData data) + { + if (overloads == null) + overloads = new List<CompletionData> (); + overloads.Add ((CompletionData)data); + sorted = null; + } + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionCategory ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData.CompletionCategory { + get { + return (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionCategory)base.CompletionCategory; + } + set { + base.CompletionCategory = (CompletionCategory)value; + } + } + + ICSharpCode.NRefactory6.CSharp.Completion.DisplayFlags ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData.DisplayFlags { + get { + return (ICSharpCode.NRefactory6.CSharp.Completion.DisplayFlags)base.DisplayFlags; + } + set { + base.DisplayFlags = (DisplayFlags)value; + } + } + + List<CompletionData> sorted; + + IEnumerable<ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData> ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData.OverloadedData { + get { + return (IEnumerable<ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData>)OverloadedData; + } + } + + public override IReadOnlyList<CompletionData> OverloadedData { + get { + if (overloads == null) + return new CompletionData[] { this }; + + if (sorted == null) { + sorted = new List<CompletionData> (overloads); + sorted.Add (this); + // sorted.Sort (new OverloadSorter ()); + } + return sorted; + } + } + + protected readonly ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler; + + ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData.KeyHandler { + get { + return keyHandler; + } + } + + public RoslynCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler) + { + this.keyHandler = keyHandler; + } + + public RoslynCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string text) : base (text) + { + this.keyHandler = keyHandler; + } + + public RoslynCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string text, IconId icon) : base (text, icon) + { + this.keyHandler = keyHandler; + } + + public RoslynCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string text, IconId icon, string description) : base (text, icon, description) + { + this.keyHandler = keyHandler; + } + + public RoslynCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, string displayText, IconId icon, string description, string completionText) : base (displayText, icon, description, completionText) + { + this.keyHandler = keyHandler; + } + +// class OverloadSorter : IComparer<ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData> +// { +// public OverloadSorter () +// { +// } +// +// public int Compare (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData x, ICSharpCode.NRefactory6.CSharp.Completion.ICompletionData y) +// { +// var mx = ((RoslynCompletionData)x).Entity as IMember; +// var my = ((RoslynCompletionData)y).Entity as IMember; +// int result; +// +// if (mx is ITypeDefinition && my is ITypeDefinition) { +// result = ((((ITypeDefinition)mx).TypeParameters.Count).CompareTo (((ITypeDefinition)my).TypeParameters.Count)); +// if (result != 0) +// return result; +// } +// +// if (mx is IMethod && my is IMethod) { +// return MethodParameterDataProvider.MethodComparer ((IMethod)mx, (IMethod)my); +// } +// string sx = mx.ReflectionName;// ambience.GetString (mx, flags); +// string sy = my.ReflectionName;// ambience.GetString (my, flags); +// result = sx.Length.CompareTo (sy.Length); +// return result == 0 ? string.Compare (sx, sy) : result; +// } +// } + + } + +} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynParameterHintingFactory.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynParameterHintingFactory.cs new file mode 100644 index 0000000000..2982e02d66 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynParameterHintingFactory.cs @@ -0,0 +1,296 @@ +// +// RoslynParameterHintingFactory.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory6.CSharp.Completion; +using Microsoft.CodeAnalysis; +using System.Collections.Immutable; +using ICSharpCode.NRefactory6.CSharp; +using System.Linq; +using MonoDevelop.Ide.CodeCompletion; +using MonoDevelop.Core; +using MonoDevelop.Ide.TypeSystem; +using System.Text.RegularExpressions; + +namespace MonoDevelop.CSharp.Completion +{ + class RoslynParameterHintingFactory : IParameterHintingDataFactory + { + #region IParameterHintingDataFactory implementation + + IParameterHintingData IParameterHintingDataFactory.CreateConstructorProvider (Microsoft.CodeAnalysis.IMethodSymbol constructor) + { + return new ParameterHintingData (constructor); + } + + IParameterHintingData IParameterHintingDataFactory.CreateMethodDataProvider (Microsoft.CodeAnalysis.IMethodSymbol method) + { + return new ParameterHintingData (method); + } + + IParameterHintingData IParameterHintingDataFactory.CreateDelegateDataProvider (Microsoft.CodeAnalysis.ITypeSymbol delegateType) + { + return new DelegateParameterHintingData (delegateType); + } + + IParameterHintingData IParameterHintingDataFactory.CreateIndexerParameterDataProvider (Microsoft.CodeAnalysis.IPropertySymbol indexer, Microsoft.CodeAnalysis.SyntaxNode resolvedNode) + { + return new ParameterHintingData (indexer); + } + + IParameterHintingData IParameterHintingDataFactory.CreateTypeParameterDataProvider (Microsoft.CodeAnalysis.INamedTypeSymbol type) + { + return new TypeParameterHintingData (type); + } + + IParameterHintingData IParameterHintingDataFactory.CreateTypeParameterDataProvider (Microsoft.CodeAnalysis.IMethodSymbol method) + { + return new TypeParameterHintingData (method); + } + + IParameterHintingData IParameterHintingDataFactory.CreateArrayDataProvider (Microsoft.CodeAnalysis.IArrayTypeSymbol arrayType) + { + return new ArrayParameterHintingData (arrayType); + } + + #endregion + + class ParameterHintingData : MonoDevelop.Ide.CodeCompletion.ParameterHintingData, IParameterHintingData + { + public ParameterHintingData (IMethodSymbol symbol) : base (symbol) + { + } + + public ParameterHintingData (IPropertySymbol symbol) : base (symbol) + { + } + public override TooltipInformation CreateTooltipInformation (MonoDevelop.Ide.Editor.TextEditor editor, MonoDevelop.Ide.Editor.DocumentContext ctx, int currentParameter, bool smartWrap) + { + return CreateTooltipInformation (editor, ctx, Symbol, currentParameter, smartWrap); + } + + internal static TooltipInformation CreateTooltipInformation (MonoDevelop.Ide.Editor.TextEditor editor, MonoDevelop.Ide.Editor.DocumentContext ctx, ISymbol sym, int currentParameter, bool smartWrap) + { + var tooltipInfo = new TooltipInformation (); + var sig = new SignatureMarkupCreator (ctx, editor != null ? editor.CaretOffset : 0); + sig.HighlightParameter = currentParameter; + sig.BreakLineAfterReturnType = smartWrap; + try { + tooltipInfo.SignatureMarkup = sig.GetMarkup (sym); + } catch (Exception e) { + LoggingService.LogError ("Got exception while creating markup for :" + sym, e); + return new TooltipInformation (); + } + tooltipInfo.SummaryMarkup = Ambience.GetSummaryMarkup (sym) ?? ""; + + if (sym is IMethodSymbol) { + var method = (IMethodSymbol)sym; + if (method.IsExtensionMethod && method.ReducedFrom != null && method.ReducedFrom.ContainingType != null) { + tooltipInfo.AddCategory (GettextCatalog.GetString ("Extension Method from"), method.ReducedFrom.ContainingType.Name); + } + } + int paramIndex = currentParameter; + +// if (Symbol is IMethodSymbol && ((IMethodSymbol)Symbol).IsExtensionMethod) +// paramIndex++; + var list = GetParameterList (sym); + paramIndex = Math.Min (list.Length - 1, paramIndex); + + var curParameter = paramIndex >= 0 && paramIndex < list.Length ? list [paramIndex] : null; + if (curParameter != null) { + + string docText = Ambience.GetDocumentation (sym); + if (!string.IsNullOrEmpty (docText)) { + string text = docText; + Regex paramRegex = new Regex ("(\\<param\\s+name\\s*=\\s*\"" + curParameter.Name + "\"\\s*\\>.*?\\</param\\>)", RegexOptions.Compiled); + Match match = paramRegex.Match (docText); + + if (match.Success) { + text = Ambience.GetDocumentationMarkup (sym, match.Groups [1].Value); + if (!string.IsNullOrWhiteSpace (text)) + tooltipInfo.AddCategory (GettextCatalog.GetString ("Parameter"), text); + } + } + if (curParameter.Type.TypeKind == TypeKind.Delegate) + tooltipInfo.AddCategory (GettextCatalog.GetString ("Delegate Info"), sig.GetDelegateInfo (curParameter.Type)); + } + return tooltipInfo; + } + + static ImmutableArray<IParameterSymbol> GetParameterList (ISymbol data) + { + var ms = data as IMethodSymbol; + if (ms != null) + return ms.Parameters; + + var ps = data as IPropertySymbol; + if (ps != null) + return ps.Parameters; + + return ImmutableArray<IParameterSymbol>.Empty; + } + + public override string GetParameterName (int currentParameter) + { + var list = GetParameterList (Symbol); + if (currentParameter < 0 || currentParameter >= list.Length) + throw new ArgumentOutOfRangeException ("currentParameter"); + return list [currentParameter].Name; + } + + public override int ParameterCount { + get { + return GetParameterList (Symbol).Length; + } + } + + public override bool IsParameterListAllowed { + get { + var param = GetParameterList (Symbol).LastOrDefault (); + return param != null && param.IsParams; + } + } + } + + class DelegateParameterHintingData : MonoDevelop.Ide.CodeCompletion.ParameterHintingData, IParameterHintingData + { + readonly IMethodSymbol invocationMethod; + + public DelegateParameterHintingData (ITypeSymbol symbol) : base (symbol) + { + this.invocationMethod = symbol.GetDelegateInvokeMethod (); + } + + public override string GetParameterName (int currentParameter) + { + var list = invocationMethod.Parameters; + if (currentParameter < 0 || currentParameter >= list.Length) + throw new ArgumentOutOfRangeException ("currentParameter"); + return list [currentParameter].Name; + } + + public override int ParameterCount { + get { + return invocationMethod.Parameters.Length; + } + } + + public override bool IsParameterListAllowed { + get { + var param = invocationMethod.Parameters.LastOrDefault (); + return param != null && param.IsParams; + } + } + public override TooltipInformation CreateTooltipInformation (MonoDevelop.Ide.Editor.TextEditor editor, MonoDevelop.Ide.Editor.DocumentContext ctx, int currentParameter, bool smartWrap) + { + return ParameterHintingData.CreateTooltipInformation (editor, ctx, invocationMethod, currentParameter, smartWrap); + } + + } + + class ArrayParameterHintingData : MonoDevelop.Ide.CodeCompletion.ParameterHintingData, IParameterHintingData + { + readonly IArrayTypeSymbol arrayType; + + public ArrayParameterHintingData (IArrayTypeSymbol arrayType) : base (arrayType) + { + this.arrayType = arrayType; + } + + public override string GetParameterName (int currentParameter) + { + return null; + } + + public override int ParameterCount { + get { + return arrayType.Rank; + } + } + + public override bool IsParameterListAllowed { + get { + return false; + } + } + + public override TooltipInformation CreateTooltipInformation (MonoDevelop.Ide.Editor.TextEditor editor, MonoDevelop.Ide.Editor.DocumentContext ctx, int currentParameter, bool smartWrap) + { + var sig = new SignatureMarkupCreator (ctx, editor != null ? editor.CaretOffset : 0) { + HighlightParameter = currentParameter + }; + return new TooltipInformation { + SignatureMarkup = sig.GetArrayIndexerMarkup (arrayType) + }; + } + + } + + class TypeParameterHintingData : MonoDevelop.Ide.CodeCompletion.ParameterHintingData, IParameterHintingData + { + public TypeParameterHintingData (IMethodSymbol symbol) : base (symbol) + { + } + + public TypeParameterHintingData (INamedTypeSymbol symbol) : base (symbol) + { + } + + static ImmutableArray<ITypeParameterSymbol> GetTypeParameterList (IParameterHintingData data) + { + var ms = data.Symbol as IMethodSymbol; + if (ms != null) + return ms.TypeParameters; + + var ps = data.Symbol as INamedTypeSymbol; + if (ps != null) + return ps.TypeParameters; + + return ImmutableArray<ITypeParameterSymbol>.Empty; + } + + public override string GetParameterName (int currentParameter) + { + var list = GetTypeParameterList (this); + if (currentParameter < 0 || currentParameter >= list.Length) + throw new ArgumentOutOfRangeException ("currentParameter"); + return list [currentParameter].Name; + } + + public override int ParameterCount { + get { + return GetTypeParameterList (this).Length; + } + } + + public override bool IsParameterListAllowed { + get { + return false; + } + } + } + } +} + diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs new file mode 100644 index 0000000000..6a0dee624b --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs @@ -0,0 +1,451 @@ +// +// CSharpCompletionTextEditorExtension.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2011 Xamarin <http://xamarin.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using MonoDevelop.Ide.CodeCompletion; +using Microsoft.CodeAnalysis; +using GLib; +using System.Collections.Generic; +using MonoDevelop.Core; +using MonoDevelop.Ide.TypeSystem; +using MonoDevelop.Ide.Editor.Extension; +using Xwt; +using MonoDevelop.Ide; + +namespace MonoDevelop.CSharp.Completion +{ + class RoslynSymbolCompletionData : RoslynCompletionData, ICSharpCode.NRefactory6.CSharp.Completion.ISymbolCompletionData + { + readonly ISymbol symbol; + + public ISymbol Symbol { + get { + return symbol; + } + } + + public override string DisplayText { + get { + return text ?? symbol.Name; + } + set { + text = value; + } + } + + public override string CompletionText { + get { + return text ?? symbol.Name; + } + set { + throw new NotSupportedException (); + } + } + + public override MonoDevelop.Core.IconId Icon { + get { + return MonoDevelop.Ide.TypeSystem.Stock.GetStockIcon (symbol); + } + set { + throw new NotSupportedException (); + } + } + + public bool IsDelegateExpected { get; set; } + + + string text; + protected readonly CSharpCompletionTextEditorExtension ext; + + + public RoslynSymbolCompletionData (ICSharpCode.NRefactory6.CSharp.Completion.ICompletionKeyHandler keyHandler, CSharpCompletionTextEditorExtension ext, ISymbol symbol, string text = null) : base (keyHandler) + { + this.ext = ext; + this.text = text; + this.symbol = symbol; + } + + static readonly SymbolDisplayFormat nameOnlyFormat = + new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly, + propertyStyle: SymbolDisplayPropertyStyle.NameOnly, + genericsOptions: SymbolDisplayGenericsOptions.None, + memberOptions: SymbolDisplayMemberOptions.None, + parameterOptions: + SymbolDisplayParameterOptions.None, + miscellaneousOptions: + SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | + SymbolDisplayMiscellaneousOptions.UseSpecialTypes); + + protected virtual string GetInsertionText () + { + if (text != null) + return text; + return symbol.ToDisplayString (nameOnlyFormat); + } + + public override TooltipInformation CreateTooltipInformation (bool smartWrap) + { + return CreateTooltipInformation (ext.Editor, ext.DocumentContext, Symbol, smartWrap); + } + + public static TooltipInformation CreateTooltipInformation (MonoDevelop.Ide.Editor.TextEditor editor, MonoDevelop.Ide.Editor.DocumentContext ctx, ISymbol entity, bool smartWrap, bool createFooter = false) + { + if (ctx != null) { + if (ctx.ParsedDocument == null || ctx.AnalysisDocument == null) + LoggingService.LogError ("Signature markup creator created with invalid context." + Environment.NewLine + Environment.StackTrace); + } + + var tooltipInfo = new TooltipInformation (); +// if (resolver == null) +// resolver = file != null ? file.GetResolver (compilation, textEditorData.Caret.Location) : new CSharpResolver (compilation); + var sig = new SignatureMarkupCreator (ctx, editor != null ? editor.CaretOffset : 0); + sig.BreakLineAfterReturnType = smartWrap; + try { + tooltipInfo.SignatureMarkup = sig.GetMarkup (entity); + } catch (Exception e) { + LoggingService.LogError ("Got exception while creating markup for :" + entity, e); + return new TooltipInformation (); + } + tooltipInfo.SummaryMarkup = Ambience.GetSummaryMarkup (entity) ?? ""; + +// if (entity is IMember) { +// var evt = (IMember)entity; +// if (evt.ReturnType.Kind == TypeKind.Delegate) { +// tooltipInfo.AddCategory (GettextCatalog.GetString ("Delegate Info"), sig.GetDelegateInfo (evt.ReturnType)); +// } +// } + if (entity is IMethodSymbol) { + var method = (IMethodSymbol)entity; + if (method.IsExtensionMethod) { + tooltipInfo.AddCategory (GettextCatalog.GetString ("Extension Method from"), method.ContainingType.Name); + } + } + if (createFooter) { + tooltipInfo.FooterMarkup = sig.CreateFooter (entity); + } + return tooltipInfo; + } + + public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, MonoDevelop.Ide.Editor.Extension.KeyDescriptor descriptor) + { + string partialWord = GetCurrentWord (window); + int skipChars = 0; + bool runParameterCompletionCommand = false; + bool runCompletionCompletionCommand = false; + var method = Symbol as IMethodSymbol; + + bool addParens = CompletionTextEditorExtension.AddParenthesesAfterCompletion; + bool addOpeningOnly = CompletionTextEditorExtension.AddOpeningOnly; + var Editor = ext.Editor; + var Policy = ext.FormattingPolicy; + string insertionText = this.GetInsertionText(); + + if (addParens && !IsDelegateExpected && method != null && !HasNonMethodMembersWithSameName (Symbol) && !IsBracketAlreadyInserted (ext, method)) { + var line = Editor.GetLine (Editor.CaretLine); + //var start = window.CodeCompletionContext.TriggerOffset + partialWord.Length + 2; + //var end = line.Offset + line.Length; + //string textToEnd = start < end ? Editor.GetTextBetween (start, end) : ""; + bool addSpace = Policy.SpaceAfterMethodCallName && MonoDevelop.Ide.Editor.DefaultSourceEditorOptions.Instance.OnTheFlyFormatting; + + int exprStart = window.CodeCompletionContext.TriggerOffset - 1; + while (exprStart > line.Offset) { + char ch = Editor.GetCharAt (exprStart); + if (ch != '.' && ch != '_' && !char.IsLetterOrDigit (ch)) + break; + exprStart--; + } + bool insertSemicolon = InsertSemicolon(ext, exprStart); + if (Symbol is IMethodSymbol && ((IMethodSymbol)Symbol).MethodKind == MethodKind.Constructor) + insertSemicolon = false; + //int pos; + + var keys = new [] { SpecialKey.Return, SpecialKey.Tab, SpecialKey.Space }; + if (keys.Contains (descriptor.SpecialKey) || descriptor.KeyChar == '.') { + if (HasAnyOverloadWithParameters (method)) { + if (addOpeningOnly) { + insertionText += RequireGenerics (method) ? "<|" : (addSpace ? " (|" : "(|"); + skipChars = 0; + } else { + if (descriptor.KeyChar == '.') { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<> ()" : "<>()"; + } else { + insertionText += addSpace ? " ()" : "()"; + } + skipChars = 0; + } else { + if (insertSemicolon) { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<|> ();" : "<|>();"; + skipChars = addSpace ? 5 : 4; + } else { + insertionText += addSpace ? " (|);" : "(|);"; + skipChars = 2; + } + } else { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<|> ()" : "<|>()"; + skipChars = addSpace ? 4 : 3; + } else { + insertionText += addSpace ? " (|)" : "(|)"; + skipChars = 1; + } + } + } + } + runParameterCompletionCommand = true; + } else { + if (addOpeningOnly) { + insertionText += RequireGenerics (method) ? "<|" : (addSpace ? " (|" : "(|"); + skipChars = 0; + } else { + if (descriptor.KeyChar == '.') { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<> ().|" : "<>().|"; + } else { + insertionText += addSpace ? " ().|" : "().|"; + } + skipChars = 0; + } else { + if (insertSemicolon) { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<|> ();" : "<|>();"; + } else { + insertionText += addSpace ? " ();|" : "();|"; + } + + } else { + if (RequireGenerics (method)) { + insertionText += addSpace ? "<|> ()" : "<|>()"; + } else { + insertionText += addSpace ? " ()|" : "()|"; + } + + } + } + } + } + if (descriptor.KeyChar == '(') { + var skipCharList = Editor.SkipChars; + if (skipCharList.Count > 0) { + var lastSkipChar = skipCharList[skipCharList.Count - 1]; + if (lastSkipChar.Offset == (window.CodeCompletionContext.TriggerOffset + partialWord.Length) && lastSkipChar.Char == ')') + Editor.RemoveText (lastSkipChar.Offset, 1); + } + } + } + if (descriptor.KeyChar == ';') { + insertionText += addSpace ? " ()" : "()"; + + } + ka |= KeyActions.Ignore; + } + if ((DisplayFlags & DisplayFlags.NamedArgument) == DisplayFlags.NamedArgument && + CompletionTextEditorExtension.AddParenthesesAfterCompletion && + (descriptor.SpecialKey == SpecialKey.Tab || + descriptor.SpecialKey == SpecialKey.Return || + descriptor.SpecialKey == SpecialKey.Space)) { + if (true/*Policy.AroundAssignmentParentheses */) + insertionText += " "; + insertionText += "="; + if (/*Policy.AroundAssignmentParentheses && */descriptor.SpecialKey != SpecialKey.Space) + insertionText += " "; + runCompletionCompletionCommand = true; + } + window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, partialWord, insertionText); + int offset = Editor.CaretOffset; + for (int i = 0; i < skipChars; i++) { + Editor.AddSkipChar (offset, Editor.GetCharAt (offset)); + offset++; + } + + if (runParameterCompletionCommand && IdeApp.Workbench != null) { + Application.Invoke (delegate { + ext.RunParameterCompletionCommand (); + }); + } + + if (runCompletionCompletionCommand && IdeApp.Workbench != null) { + Application.Invoke (delegate { + ext.RunCompletionCommand (); + }); + } + } + + static bool IsBracketAlreadyInserted (CSharpCompletionTextEditorExtension ext, IMethodSymbol method) + { + var Editor = ext.Editor; + int offset = Editor.CaretOffset; + while (offset < Editor.Length) { + char ch = Editor.GetCharAt (offset); + if (!char.IsLetterOrDigit (ch)) + break; + offset++; + } + while (offset < Editor.Length) { + char ch = Editor.GetCharAt (offset); + if (!char.IsWhiteSpace (ch)) + return ch == '(' || ch == '<' && RequireGenerics (method); + offset++; + } + return false; + } + + + + internal static bool InsertSemicolon (CSharpCompletionTextEditorExtension ext, int exprStart) + { + var Editor = ext.Editor; + int offset = exprStart; + while (offset > 0) { + char ch = Editor.GetCharAt (offset); + if (!char.IsWhiteSpace (ch)) { + if (ch != '{' && ch != '}' && ch != ';') + return false; + break; + } + offset--; + } + + offset = Editor.CaretOffset; + while (offset < Editor.Length) { + char ch = Editor.GetCharAt (offset); + if (!char.IsLetterOrDigit (ch)) + break; + offset++; + } + while (offset < Editor.Length) { + char ch = Editor.GetCharAt (offset); + if (!char.IsWhiteSpace (ch)) + return char.IsLetter (ch) || ch == '}'; + offset++; + } + return true; + } + + internal static bool HasAnyOverloadWithParameters (IMethodSymbol method) + { + if (method.MethodKind == MethodKind.Constructor) + return method.ContainingType.GetMembers() + .OfType<IMethodSymbol>() + .Where(m => m.MethodKind == MethodKind.Constructor) + .Any (m => m.Parameters.Length > 0); + return method.ContainingType + .GetMembers() + .OfType<IMethodSymbol>() + .Any (m => m.Name == method.Name && m.Parameters.Length > 0); + } + + static bool HasNonMethodMembersWithSameName (ISymbol member) + { + var method = member as IMethodSymbol; + if (method != null && method.MethodKind == MethodKind.Constructor) + return false; + if (member.ContainingType == null) + return false; + return member.ContainingType + .GetMembers () + .Any (e => e.Kind != SymbolKind.Method && e.Name == member.Name); + } + + static bool RequireGenerics (IMethodSymbol method) + { + System.Collections.Immutable.ImmutableArray<ITypeSymbol> typeArgs; + if (method.MethodKind == MethodKind.Constructor) { + typeArgs = method.ContainingType.TypeArguments; + } else { + typeArgs = method.TypeArguments; + } + + if (!typeArgs.Any (ta => ta.TypeKind == TypeKind.TypeParameter)) + return false; + var testMethod = method.ReducedFrom ?? method; + return typeArgs.Any (t => !testMethod.Parameters.Any (p => ContainsType(p.Type, t))); + } + + static bool ContainsType (ITypeSymbol testType, ITypeSymbol searchType) + { + if (testType == null) + return false; + if (testType == searchType) + return true; + var namedTypeSymbol = testType as INamedTypeSymbol; + if (namedTypeSymbol != null) { + foreach (var arg in namedTypeSymbol.TypeParameters) + if (ContainsType (arg, searchType)) + return true; + } + return false; + } + + public override int CompareTo (object obj) + { + var anonymousMethodCompletionData = obj as AnonymousMethodCompletionData; + if (anonymousMethodCompletionData == null) + return 1; + var objectCreationData = obj as ObjectCreationCompletionData; + if (objectCreationData == null) + return 1; + + + return base.CompareTo (obj); + } + + +// public static TooltipInformation CreateTooltipInformation (ICompilation compilation, CSharpUnresolvedFile file, TextEditorData textEditorData, MonoDevelop.CSharp.Formatting.CSharpFormattingPolicy formattingPolicy, IType type, bool smartWrap, bool createFooter = false) +// { +// var tooltipInfo = new TooltipInformation (); +// var resolver = file != null ? file.GetResolver (compilation, textEditorData.Caret.Location) : new CSharpResolver (compilation); +// var sig = new SignatureMarkupCreator (resolver, formattingPolicy.CreateOptions ()); +// sig.BreakLineAfterReturnType = smartWrap; +// try { +// tooltipInfo.SignatureMarkup = sig.GetMarkup (type.IsParameterized ? type.GetDefinition () : type); +// } catch (Exception e) { +// LoggingService.LogError ("Got exception while creating markup for :" + type, e); +// return new TooltipInformation (); +// } +// if (type.IsParameterized) { +// var typeInfo = new StringBuilder (); +// for (int i = 0; i < type.TypeParameterCount; i++) { +// typeInfo.AppendLine (type.GetDefinition ().TypeParameters [i].Name + " is " + sig.GetTypeReferenceString (type.TypeArguments [i])); +// } +// tooltipInfo.AddCategory ("Type Parameters", typeInfo.ToString ()); +// } +// +// var def = type.GetDefinition (); +// if (def != null) { +// if (createFooter) +// tooltipInfo.FooterMarkup = sig.CreateFooter (def); +// tooltipInfo.SummaryMarkup = AmbienceService.GetSummaryMarkup (def) ?? ""; +// } +// return tooltipInfo; +// } + } + +} diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/TypeParameterDataProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/TypeParameterDataProvider.cs deleted file mode 100644 index 0e5f2ce907..0000000000 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/TypeParameterDataProvider.cs +++ /dev/null @@ -1,163 +0,0 @@ -// -// TemplateParameterDataProvider.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Collections.Generic; -using System.Text; -using System.Xml; - -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Ide.CodeCompletion; -using MonoDevelop.CSharp.Formatting; -using MonoDevelop.CSharp.Parser; -using System.Text.RegularExpressions; -using ICSharpCode.NRefactory.CSharp; -using MonoDevelop.CSharp.Resolver; -using Mono.TextEditor; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.CSharp.Resolver; -using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory.Completion; - -namespace MonoDevelop.CSharp.Completion -{ - class TypeParameterDataProvider: IParameterDataProvider - { - int startOffset; - //CSharpCompletionTextEditorExtension ext; - - List<IType> types; - List<IMethod> methods; - CSharpAmbience ambience = new CSharpAmbience (); - - public int StartOffset { - get { - return startOffset; - } - } - - public TypeParameterDataProvider (int startOffset, CSharpCompletionTextEditorExtension ext, IEnumerable<IType> types) - { - this.startOffset = startOffset; - // this.ext = ext; - this.types = new List<IType> (types); - } - - public TypeParameterDataProvider (int startOffset, CSharpCompletionTextEditorExtension ext, IEnumerable<IMethod> methods) - { - this.startOffset = startOffset; - // this.ext = ext; - this.methods = new List<IMethod> (methods); - } - - static int TypeComparer (IType left, IType right) - { - return left.TypeParameterCount - right.TypeParameterCount; - } - - #region IParameterDataProvider implementation - - protected virtual string GetPrefix (IMethod method) - { - var flags = OutputFlags.ClassBrowserEntries | OutputFlags.IncludeMarkup | OutputFlags.IncludeGenerics; - return ambience.GetString (method.ReturnType, flags) + " "; - } - - public string GetHeading (int overload, string[] parameterMarkup, int currentParameter) - { - var result = new StringBuilder (); - result.Append ("<b>"); - if (methods != null) { - result.Append (ambience.GetString (methods [overload], OutputFlags.UseFullName | OutputFlags.IncludeMarkup)); - } else { - result.Append (ambience.GetString (types [overload], OutputFlags.UseFullName | OutputFlags.IncludeMarkup)); - } - result.Append ("</b>"); - result.Append ("<"); - int parameterCount = 0; - foreach (string parameter in parameterMarkup) { - if (parameterCount > 0) - result.Append (", "); - result.Append (parameter); - parameterCount++; - } - result.Append (">"); - - return result.ToString (); - } - - public string GetDescription (int overload, int currentParameter) - { - return ""; - } - - public string GetParameterDescription (int overload, int paramIndex) - { - if (methods != null) - return ambience.GetString (methods[overload].TypeParameters [paramIndex], OutputFlags.AssemblyBrowserDescription | OutputFlags.HideExtensionsParameter | OutputFlags.IncludeGenerics | OutputFlags.IncludeModifiers | OutputFlags.HighlightName); - - var type = types[overload]; - - if (paramIndex < 0 || paramIndex >= type.TypeParameterCount) - return ""; - - return ambience.GetString (type.GetDefinition ().TypeParameters [paramIndex], OutputFlags.AssemblyBrowserDescription | OutputFlags.HideExtensionsParameter | OutputFlags.IncludeGenerics | OutputFlags.IncludeModifiers | OutputFlags.HighlightName); - } - - public int GetParameterCount (int overload) - { - if (overload >= Count) - return -1; - - if (methods != null) - return methods[overload].TypeParameters.Count; - var type = types[overload]; - return type != null ? type.TypeParameterCount : 0; - } - - public string GetParameterName (int overload, int paramIndex) - { - // unused - return "T"; - } - - - public bool AllowParameterList (int overload) - { - return false; - } - - public int Count { - get { - if (methods != null) - return methods.Count; - return types != null ? types.Count : 0; - } - } - #endregion - } -} - |