Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs')
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/RoslynSymbolCompletionData.cs451
1 files changed, 451 insertions, 0 deletions
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;
+// }
+ }
+
+}