7 changed files with 2502 additions and 9 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,349 @@
@@ -0,0 +1,349 @@
|
||||
//
|
||||
// CSharpCompletionEngineBase.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 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.Linq; |
||||
using System.Text; |
||||
|
||||
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||
using ICSharpCode.NRefactory.Editor; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.Semantics; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
/// <summary>
|
||||
/// Acts as a common base between code completion and parameter completion.
|
||||
/// </summary>
|
||||
public class CSharpCompletionEngineBase |
||||
{ |
||||
protected IDocument document; |
||||
protected int offset; |
||||
protected TextLocation location; |
||||
|
||||
protected ITypeDefinition currentType; |
||||
protected IMember currentMember; |
||||
|
||||
#region Input properties
|
||||
public ITypeResolveContext ctx { get; set; } |
||||
public CompilationUnit Unit { get; set; } |
||||
public CSharpParsedFile CSharpParsedFile { get; set; } |
||||
public IProjectContent ProjectContent { get; set; } |
||||
#endregion
|
||||
|
||||
protected void SetOffset (int offset) |
||||
{ |
||||
this.offset = offset; |
||||
this.location = document.GetLocation (offset); |
||||
|
||||
this.currentType = CSharpParsedFile.GetInnermostTypeDefinition (location); |
||||
this.currentMember = CSharpParsedFile.GetMember (location); |
||||
} |
||||
|
||||
#region Context helper methods
|
||||
protected bool IsInsideComment () |
||||
{ |
||||
return IsInsideComment (offset); |
||||
} |
||||
|
||||
protected bool IsInsideComment (int offset) |
||||
{ |
||||
var loc = document.GetLocation (offset); |
||||
return Unit.GetNodeAt<ICSharpCode.NRefactory.CSharp.Comment> (loc.Line, loc.Column) != null; |
||||
} |
||||
|
||||
protected bool IsInsideDocComment () |
||||
{ |
||||
var loc = document.GetLocation (offset); |
||||
var cmt = Unit.GetNodeAt<ICSharpCode.NRefactory.CSharp.Comment> (loc.Line, loc.Column - 1); |
||||
return cmt != null && cmt.CommentType == CommentType.Documentation; |
||||
} |
||||
|
||||
protected bool IsInsideString () |
||||
{ |
||||
return IsInsideString (offset); |
||||
} |
||||
|
||||
protected bool IsInsideString (int offset) |
||||
{ |
||||
var loc = document.GetLocation (offset); |
||||
var expr = Unit.GetNodeAt<PrimitiveExpression> (loc.Line, loc.Column); |
||||
return expr != null && expr.Value is string; |
||||
} |
||||
#endregion
|
||||
|
||||
#region Basic parsing/resolving functions
|
||||
protected void AppendMissingClosingBrackets (StringBuilder wrapper, string memberText, bool appendSemicolon) |
||||
{ |
||||
var bracketStack = new Stack<char> (); |
||||
|
||||
bool isInString = false, isInChar = false; |
||||
bool isInLineComment = false, isInBlockComment = false; |
||||
|
||||
for (int pos = 0; pos < memberText.Length; pos++) { |
||||
char ch = memberText [pos]; |
||||
switch (ch) { |
||||
case '(': |
||||
case '[': |
||||
case '{': |
||||
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment) |
||||
bracketStack.Push (ch); |
||||
break; |
||||
case ')': |
||||
case ']': |
||||
case '}': |
||||
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment) |
||||
if (bracketStack.Count > 0) |
||||
bracketStack.Pop (); |
||||
break; |
||||
case '\r': |
||||
case '\n': |
||||
isInLineComment = false; |
||||
break; |
||||
case '/': |
||||
if (isInBlockComment) { |
||||
if (pos > 0 && memberText [pos - 1] == '*') |
||||
isInBlockComment = false; |
||||
} else if (!isInString && !isInChar && pos + 1 < memberText.Length) { |
||||
char nextChar = memberText [pos + 1]; |
||||
if (nextChar == '/') |
||||
isInLineComment = true; |
||||
if (!isInLineComment && nextChar == '*') |
||||
isInBlockComment = true; |
||||
} |
||||
break; |
||||
case '"': |
||||
if (!(isInChar || isInLineComment || isInBlockComment)) |
||||
isInString = !isInString; |
||||
break; |
||||
case '\'': |
||||
if (!(isInString || isInLineComment || isInBlockComment)) |
||||
isInChar = !isInChar; |
||||
break; |
||||
default : |
||||
break; |
||||
} |
||||
} |
||||
bool didAppendSemicolon = !appendSemicolon; |
||||
|
||||
char lastBracket = '\0'; |
||||
while (bracketStack.Count > 0) { |
||||
switch (bracketStack.Pop ()) { |
||||
case '(': |
||||
wrapper.Append (')'); |
||||
didAppendSemicolon = false; |
||||
lastBracket = ')'; |
||||
break; |
||||
case '[': |
||||
wrapper.Append (']'); |
||||
didAppendSemicolon = false; |
||||
lastBracket = ']'; |
||||
break; |
||||
case '<': |
||||
wrapper.Append ('>'); |
||||
didAppendSemicolon = false; |
||||
lastBracket = '>'; |
||||
break; |
||||
case '{': |
||||
if (!didAppendSemicolon) { |
||||
didAppendSemicolon = true; |
||||
wrapper.Append (';'); |
||||
} |
||||
|
||||
wrapper.Append ('}'); |
||||
break; |
||||
} |
||||
} |
||||
if (currentMember == null && lastBracket == ']') { |
||||
// attribute context
|
||||
wrapper.Append ("class GenAttr {}"); |
||||
} else { |
||||
if (!didAppendSemicolon) |
||||
wrapper.Append (';'); |
||||
} |
||||
} |
||||
|
||||
protected CompilationUnit ParseStub (string continuation, bool appendSemicolon = true) |
||||
{ |
||||
var mt = GetMemberTextToCaret (); |
||||
if (mt == null) |
||||
return null; |
||||
|
||||
string memberText = mt.Item1; |
||||
bool wrapInClass = mt.Item2; |
||||
|
||||
var wrapper = new StringBuilder (); |
||||
if (wrapInClass) { |
||||
wrapper.Append ("class Stub {"); |
||||
wrapper.AppendLine (); |
||||
} |
||||
|
||||
wrapper.Append (memberText); |
||||
wrapper.Append (continuation); |
||||
AppendMissingClosingBrackets (wrapper, memberText, appendSemicolon); |
||||
|
||||
if (wrapInClass) |
||||
wrapper.Append ('}'); |
||||
|
||||
TextLocation memberLocation; |
||||
if (currentMember != null) { |
||||
memberLocation = currentMember.Region.Begin; |
||||
} else if (currentType != null) { |
||||
memberLocation = currentType.Region.Begin; |
||||
} else { |
||||
memberLocation = new TextLocation (1, 1); |
||||
} |
||||
using (var stream = new System.IO.StringReader (wrapper.ToString ())) { |
||||
var parser = new CSharpParser (); |
||||
return parser.Parse (stream, wrapInClass ? memberLocation.Line - 2 : 0); |
||||
} |
||||
} |
||||
|
||||
protected Tuple<string, bool> GetMemberTextToCaret () |
||||
{ |
||||
int startOffset; |
||||
if (currentMember != null) { |
||||
startOffset = document.GetOffset (currentMember.Region.BeginLine, currentMember.Region.BeginColumn); |
||||
} else if (currentType != null) { |
||||
startOffset = document.GetOffset (currentType.Region.BeginLine, currentType.Region.BeginColumn); |
||||
} else { |
||||
startOffset = 0; |
||||
} |
||||
return Tuple.Create (document.GetText (startOffset, offset - startOffset), startOffset != 0); |
||||
} |
||||
|
||||
protected Tuple<CSharpParsedFile, AstNode, CompilationUnit> GetInvocationBeforeCursor (bool afterBracket) |
||||
{ |
||||
CompilationUnit baseUnit; |
||||
if (currentMember == null) { |
||||
baseUnit = ParseStub ("", false); |
||||
var section = baseUnit.GetNodeAt<AttributeSection> (location.Line, location.Column - 2); |
||||
var attr = section != null ? section.Attributes.LastOrDefault () : null; |
||||
if (attr != null) { |
||||
// insert target type into compilation unit, to respect the
|
||||
attr.Remove (); |
||||
var node = Unit.GetNodeAt (location) ?? Unit; |
||||
node.AddChild (attr, AttributeSection.AttributeRole); |
||||
return Tuple.Create (CSharpParsedFile, (AstNode)attr, Unit); |
||||
} |
||||
} |
||||
|
||||
if (currentMember == null && currentType == null) { |
||||
return null; |
||||
} |
||||
baseUnit = ParseStub (afterBracket ? "" : "x"); |
||||
|
||||
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; |
||||
var mref = baseUnit.GetNodeAt (location, n => n is InvocationExpression || n is ObjectCreateExpression); |
||||
AstNode expr; |
||||
if (mref is InvocationExpression) { |
||||
expr = ((InvocationExpression)mref).Target; |
||||
} else if (mref is ObjectCreateExpression) { |
||||
expr = mref; |
||||
} else { |
||||
return null; |
||||
} |
||||
|
||||
var member = Unit.GetNodeAt<AttributedNode> (memberLocation); |
||||
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation); |
||||
member2.Remove (); |
||||
member.ReplaceWith (member2); |
||||
var tsvisitor = new TypeSystemConvertVisitor (ProjectContent, CSharpParsedFile.FileName); |
||||
Unit.AcceptVisitor (tsvisitor, null); |
||||
return Tuple.Create (tsvisitor.ParsedFile, (AstNode)expr, Unit); |
||||
|
||||
/* |
||||
|
||||
///////
|
||||
if (currentMember == null && currentType == null) |
||||
return null; |
||||
|
||||
CSharpParser parser = new CSharpParser (); |
||||
int startOffset; |
||||
if (currentMember != null) { |
||||
startOffset = document.Editor.LocationToOffset (currentMember.Region.BeginLine, currentMember.Region.BeginColumn); |
||||
} else { |
||||
startOffset = document.Editor.LocationToOffset (currentType.Region.BeginLine, currentType.Region.BeginColumn); |
||||
} |
||||
string memberText = Document.Editor.GetTextBetween (startOffset, Document.Editor.Caret.Offset - 1); |
||||
|
||||
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; |
||||
StringBuilder wrapper = new StringBuilder (); |
||||
wrapper.Append ("class Stub {"); |
||||
wrapper.AppendLine (); |
||||
wrapper.Append (memberText); |
||||
|
||||
if (afterBracket) { |
||||
wrapper.Append ("();"); |
||||
} else { |
||||
wrapper.Append ("x);"); |
||||
} |
||||
|
||||
wrapper.Append (" SomeCall (); } } }"); |
||||
var stream = new System.IO.StringReader (wrapper.ToString ()); |
||||
var baseUnit = parser.Parse (stream, memberLocation.Line - 2); |
||||
stream.Close (); |
||||
var expr = baseUnit.GetNodeAt<Expression> (document.Editor.Caret.Line, document.Editor.Caret.Column); |
||||
if (expr is InvocationExpression) { |
||||
expr = ((InvocationExpression)expr).Target; |
||||
} |
||||
if (expr == null) |
||||
return null; |
||||
var member = Unit.GetNodeAt<AttributedNode> (memberLocation); |
||||
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation); |
||||
member2.Remove (); |
||||
member.ReplaceWith (member2); |
||||
|
||||
var tsvisitor = new TypeSystemConvertVisitor (ProjectContext, Document.FileName); |
||||
Unit.AcceptVisitor (tsvisitor, null); |
||||
return Tuple.Create (tsvisitor.ParsedFile, expr, Unit);*/ |
||||
} |
||||
|
||||
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression (CSharpParsedFile file, AstNode expr, CompilationUnit unit) |
||||
{ |
||||
if (expr == null) |
||||
return null; |
||||
AstNode resolveNode; |
||||
if (expr is Expression || expr is AstType) { |
||||
resolveNode = expr; |
||||
} else if (expr is VariableDeclarationStatement) { |
||||
resolveNode = ((VariableDeclarationStatement)expr).Type; |
||||
} else { |
||||
resolveNode = expr; |
||||
} |
||||
|
||||
var csResolver = new CSharpResolver (ctx, System.Threading.CancellationToken.None); |
||||
var navigator = new NodeListResolveVisitorNavigator (new[] { resolveNode }); |
||||
var visitor = new ResolveVisitor (csResolver, file, navigator); |
||||
unit.AcceptVisitor (visitor, null); |
||||
var result = visitor.Resolve (resolveNode); |
||||
var state = visitor.GetResolverStateBefore (resolveNode); |
||||
return Tuple.Create (result, state); |
||||
} |
||||
#endregion
|
||||
} |
||||
} |
@ -0,0 +1,179 @@
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// CSharpParameterCompletionEngine.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 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.Editor; |
||||
using ICSharpCode.NRefactory.Completion; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.NRefactory.Semantics; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
public class CSharpParameterCompletionEngine : CSharpCompletionEngineBase |
||||
{ |
||||
internal IParameterCompletionDataFactory factory; |
||||
|
||||
public CSharpParameterCompletionEngine (IDocument document, IParameterCompletionDataFactory factory) |
||||
{ |
||||
this.document = document; |
||||
this.factory = factory; |
||||
} |
||||
|
||||
public IParameterDataProvider GetParameterDataProvider (int offset) |
||||
{ |
||||
if (offset <= 0) |
||||
return null; |
||||
SetOffset (offset); |
||||
|
||||
char completionChar = document.GetCharAt (offset - 1); |
||||
if (completionChar != '(' && completionChar != '<' && completionChar != '[') |
||||
return null; |
||||
if (IsInsideComment () || IsInsideString ()) |
||||
return null; |
||||
|
||||
var invoke = GetInvocationBeforeCursor (true); |
||||
if (invoke == null) |
||||
return null; |
||||
|
||||
ResolveResult resolveResult; |
||||
switch (completionChar) { |
||||
case '(': |
||||
if (invoke.Item2 is ObjectCreateExpression) { |
||||
var createType = ResolveExpression (invoke.Item1, ((ObjectCreateExpression)invoke.Item2).Type, invoke.Item3); |
||||
return factory.CreateConstructorProvider (createType.Item1.Type); |
||||
} |
||||
|
||||
if (invoke.Item2 is ICSharpCode.NRefactory.CSharp.Attribute) { |
||||
var attribute = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); |
||||
if (attribute == null || attribute.Item1 == null) |
||||
return null; |
||||
return factory.CreateConstructorProvider (attribute.Item1.Type); |
||||
} |
||||
|
||||
var invocationExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); |
||||
|
||||
if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError) |
||||
return null; |
||||
resolveResult = invocationExpression.Item1; |
||||
if (resolveResult is MethodGroupResolveResult) |
||||
return factory.CreateMethodDataProvider (resolveResult as MethodGroupResolveResult); |
||||
if (resolveResult is MemberResolveResult) { |
||||
if (resolveResult.Type.Kind == TypeKind.Delegate) |
||||
return factory.CreateDelegateDataProvider (resolveResult.Type); |
||||
var mr = resolveResult as MemberResolveResult; |
||||
if (mr.Member is IMethod) |
||||
return factory.CreateMethodDataProvider ((IMethod)mr.Member); |
||||
} |
||||
|
||||
//
|
||||
// if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) {
|
||||
// if (resolveResult is ThisResolveResult)
|
||||
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult);
|
||||
// if (resolveResult is BaseResolveResult)
|
||||
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult);
|
||||
// }
|
||||
// IType resolvedType = resolver.SearchType (resolveResult.ResolvedType);
|
||||
// if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) {
|
||||
// return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType);
|
||||
// }
|
||||
break; |
||||
|
||||
// case '<':
|
||||
// if (string.IsNullOrEmpty (result.Expression))
|
||||
// return null;
|
||||
// return new NRefactoryTemplateParameterDataProvider (textEditorData, resolver, GetUsedNamespaces (), result, new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
|
||||
// case '[': {
|
||||
// ResolveResult resolveResult = resolver.Resolve (result, new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
|
||||
// if (resolveResult != null && !resolveResult.StaticResolve) {
|
||||
// IType type = dom.GetType (resolveResult.ResolvedType);
|
||||
// if (type != null)
|
||||
// return new NRefactoryIndexerParameterDataProvider (textEditorData, type, result.Expression);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
} |
||||
return null; |
||||
} |
||||
|
||||
List<string> GetUsedNamespaces () |
||||
{ |
||||
var scope = CSharpParsedFile.GetUsingScope (location); |
||||
var result = new List<string> (); |
||||
while (scope != null) { |
||||
result.Add (scope.NamespaceName); |
||||
foreach (var u in scope.Usings) { |
||||
var ns = u.ResolveNamespace (ctx); |
||||
if (ns == null) |
||||
continue; |
||||
result.Add (ns.NamespaceName); |
||||
} |
||||
scope = scope.Parent; |
||||
} |
||||
return result; |
||||
} |
||||
/* |
||||
public override bool GetParameterCompletionCommandOffset (out int cpos) |
||||
{ |
||||
// Start calculating the parameter offset from the beginning of the
|
||||
// current member, instead of the beginning of the file.
|
||||
cpos = textEditorData.Caret.Offset - 1; |
||||
var parsedDocument = Document.ParsedDocument; |
||||
if (parsedDocument == null) |
||||
return false; |
||||
IMember mem = currentMember; |
||||
if (mem == null || (mem is IType)) |
||||
return false; |
||||
int startPos = textEditorData.LocationToOffset (mem.Region.BeginLine, mem.Region.BeginColumn); |
||||
int parenDepth = 0; |
||||
int chevronDepth = 0; |
||||
while (cpos > startPos) { |
||||
char c = textEditorData.GetCharAt (cpos); |
||||
if (c == ')') |
||||
parenDepth++; |
||||
if (c == '>') |
||||
chevronDepth++; |
||||
if (parenDepth == 0 && c == '(' || chevronDepth == 0 && c == '<') { |
||||
int p = MethodParameterDataProvider.GetCurrentParameterIndex (CompletionWidget, cpos + 1, startPos); |
||||
if (p != -1) { |
||||
cpos++; |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
if (c == '(') |
||||
parenDepth--; |
||||
if (c == '<') |
||||
chevronDepth--; |
||||
cpos--; |
||||
} |
||||
return false; |
||||
}*/ |
||||
} |
||||
} |
||||
|
@ -0,0 +1,204 @@
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// CompletionDataWrapper.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 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 ICSharpCode.NRefactory.Completion; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
class CompletionDataWrapper |
||||
{ |
||||
CSharpCompletionEngine completion; |
||||
List<ICompletionData> result = new List<ICompletionData> (); |
||||
|
||||
public List<ICompletionData> Result { |
||||
get { |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
ICompletionDataFactory Factory { |
||||
get { |
||||
return completion.factory; |
||||
} |
||||
} |
||||
|
||||
public CompletionDataWrapper (CSharpCompletionEngine completion) |
||||
{ |
||||
this.completion = completion; |
||||
} |
||||
|
||||
public void Add (ICompletionData data) |
||||
{ |
||||
result.Add (data); |
||||
} |
||||
|
||||
public void AddCustom (string displayText, string description = null, string completionText = null) |
||||
{ |
||||
result.Add (Factory.CreateLiteralCompletionData (displayText, description, completionText)); |
||||
} |
||||
|
||||
HashSet<string> usedNamespaces = new HashSet<string> (); |
||||
|
||||
public void AddNamespace (string curNamespace, string fullNamespace) |
||||
{ |
||||
string name; |
||||
// crop prefix
|
||||
if (!string.IsNullOrEmpty (curNamespace)) { |
||||
name = fullNamespace.Substring (curNamespace.Length + 1); |
||||
} else { |
||||
name = fullNamespace; |
||||
} |
||||
|
||||
// crop suffix
|
||||
int idx = name.IndexOf ("."); |
||||
if (idx >= 0) |
||||
name = name.Substring (0, idx); |
||||
|
||||
if (string.IsNullOrEmpty (name) || usedNamespaces.Contains (name)) |
||||
return; |
||||
usedNamespaces.Add (name); |
||||
result.Add (Factory.CreateNamespaceCompletionData (name)); |
||||
} |
||||
|
||||
HashSet<string> usedTypes = new HashSet<string> (); |
||||
|
||||
public void AddType (IType type, string shortType) |
||||
{ |
||||
if (type == null || string.IsNullOrEmpty (shortType) || usedTypes.Contains (shortType)) |
||||
return; |
||||
usedTypes.Add (shortType); |
||||
result.Add (Factory.CreateTypeCompletionData (type, shortType)); |
||||
} |
||||
|
||||
Dictionary<string, List<ICompletionData>> data = new Dictionary<string, List<ICompletionData>> (); |
||||
|
||||
public void AddVariable (IVariable variable) |
||||
{ |
||||
if (data.ContainsKey (variable.Name)) |
||||
return; |
||||
data [variable.Name] = new List<ICompletionData> (); |
||||
result.Add (Factory.CreateVariableCompletionData (variable)); |
||||
} |
||||
|
||||
public void AddTypeParameter (ITypeParameter variable) |
||||
{ |
||||
if (data.ContainsKey (variable.Name)) |
||||
return; |
||||
data [variable.Name] = new List<ICompletionData> (); |
||||
result.Add (Factory.CreateVariableCompletionData (variable)); |
||||
} |
||||
|
||||
public ICompletionData AddMember (IMember member) |
||||
{ |
||||
var newData = Factory.CreateEntityCompletionData (member); |
||||
|
||||
// newData.HideExtensionParameter = HideExtensionParameter;
|
||||
string memberKey = newData.DisplayText; |
||||
if (memberKey == null) |
||||
return null; |
||||
if (member is IMember) { |
||||
newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition); |
||||
} |
||||
List<ICompletionData> existingData; |
||||
data.TryGetValue (memberKey, out existingData); |
||||
|
||||
if (existingData != null) { |
||||
var a = member as IEntity; |
||||
foreach (IEntityCompletionData md in existingData) { |
||||
var b = md.Entity; |
||||
if (a == null || b == null || a.EntityType == b.EntityType) { |
||||
md.AddOverload (newData); |
||||
newData = null; |
||||
break; |
||||
} |
||||
} |
||||
if (newData != null) { |
||||
result.Add (newData); |
||||
data [memberKey].Add (newData); |
||||
} |
||||
} else { |
||||
result.Add (newData); |
||||
data [memberKey] = new List<ICompletionData> (); |
||||
data [memberKey].Add (newData); |
||||
} |
||||
return newData; |
||||
} |
||||
|
||||
internal CompletionCategory GetCompletionCategory (ITypeDefinition type) |
||||
{ |
||||
if (type == null) |
||||
return null; |
||||
if (!completionCategories.ContainsKey (type)) |
||||
completionCategories [type] = new TypeCompletionCategory (type); |
||||
return completionCategories [type]; |
||||
} |
||||
|
||||
Dictionary<ITypeDefinition, CompletionCategory> completionCategories = new Dictionary<ITypeDefinition, CompletionCategory> (); |
||||
class TypeCompletionCategory : CompletionCategory |
||||
{ |
||||
public ITypeDefinition Type { |
||||
get; |
||||
private set; |
||||
} |
||||
|
||||
public TypeCompletionCategory (ITypeDefinition type) : base (type.FullName, null) |
||||
{ |
||||
this.Type = type; |
||||
} |
||||
|
||||
public override int CompareTo (CompletionCategory other) |
||||
{ |
||||
var compareCategory = other as TypeCompletionCategory; |
||||
if (compareCategory == null) |
||||
return 1; |
||||
|
||||
if (Type.ReflectionName == compareCategory.Type.ReflectionName) |
||||
return 0; |
||||
|
||||
// System.Object is always the smallest
|
||||
if (Type.ReflectionName == "System.Object") |
||||
return -1; |
||||
if (compareCategory.Type.ReflectionName == "System.Object") |
||||
return 1; |
||||
|
||||
/* if (Type.GetProjectContent () != null) { |
||||
if (Type.GetProjectContent ().GetInheritanceTree (Type).Any (t => t != null && t.DecoratedFullName == compareCategory.Type.DecoratedFullName)) |
||||
return 1; |
||||
return -1; |
||||
} |
||||
|
||||
// source project dom == null - try to make the opposite comparison
|
||||
if (compareCategory.Type.GetProjectContent () != null && compareCategory.Type.GetProjectContent ().GetInheritanceTree (Type).Any (t => t != null && t.DecoratedFullName == Type.DecoratedFullName)) |
||||
return -1;*/ |
||||
return 1; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// ICompletionDataFactory.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 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.TypeSystem; |
||||
using ICSharpCode.NRefactory.Completion; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
public interface ICompletionDataFactory |
||||
{ |
||||
ICompletionData CreateEntityCompletionData (IEntity entity); |
||||
|
||||
ICompletionData CreateEntityCompletionData (IEntity entity, string text); |
||||
|
||||
ICompletionData CreateTypeCompletionData (IType type, string shortType); |
||||
|
||||
/// <summary>
|
||||
/// Creates a generic completion data.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The title of the completion data
|
||||
/// </param>
|
||||
/// <param name='description'>
|
||||
/// The description of the literal.
|
||||
/// </param>
|
||||
/// <param name='insertText'>
|
||||
/// The insert text. If null, title is taken.
|
||||
/// </param>
|
||||
ICompletionData CreateLiteralCompletionData (string title, string description = null, string insertText = null); |
||||
|
||||
ICompletionData CreateNamespaceCompletionData (string name); |
||||
|
||||
ICompletionData CreateVariableCompletionData (IVariable variable); |
||||
|
||||
ICompletionData CreateVariableCompletionData (ITypeParameter parameter); |
||||
|
||||
ICompletionData CreateEventCreationCompletionData (string varName, IType delegateType, IEvent evt, string parameterDefinition, IMember currentMember, ITypeDefinition currentType); |
||||
|
||||
ICompletionData CreateNewOverrideCompletionData (int declarationBegin, ITypeDefinition type, IMember m); |
||||
} |
||||
} |
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// IParameterCopmletionFactory.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 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.TypeSystem; |
||||
using ICSharpCode.NRefactory.Completion; |
||||
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
public interface IParameterCompletionDataFactory |
||||
{ |
||||
IParameterDataProvider CreateConstructorProvider (IType type); |
||||
|
||||
IParameterDataProvider CreateMethodDataProvider (MethodGroupResolveResult par1); |
||||
|
||||
IParameterDataProvider CreateMethodDataProvider (IMethod method); |
||||
|
||||
IParameterDataProvider CreateDelegateDataProvider (IType type); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue