#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

266 lines
8.0 KiB

//
// 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;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
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> ();
bool IsAccessible(MemberLookup lookup, INamespace ns)
{
if (ns.Types.Any (t => lookup.IsAccessible (t, false)))
return true;
foreach (var child in ns.ChildNamespaces)
if (IsAccessible (lookup, child))
return true;
return false;
}
public void AddNamespace (MemberLookup lookup, INamespace ns)
{
if (usedNamespaces.Contains (ns.Name))
return;
if (!IsAccessible (lookup, ns)) {
usedNamespaces.Add (ns.Name);
return;
}
usedNamespaces.Add (ns.Name);
result.Add (Factory.CreateNamespaceCompletionData (ns));
}
public void AddAlias(string alias)
{
result.Add (Factory.CreateLiteralCompletionData (alias));
}
Dictionary<string, ICompletionData> typeDisplayText = new Dictionary<string, ICompletionData> ();
Dictionary<IType, ICompletionData> addedTypes = new Dictionary<IType, ICompletionData> ();
public ICompletionData AddType(IType type, bool showFullName, bool isInAttributeContext = false)
{
if (type == null)
throw new ArgumentNullException("type");
if (type.Name == "Void" && type.Namespace == "System" || type.Kind == TypeKind.Unknown)
return null;
if (addedTypes.ContainsKey (type))
return addedTypes[type];
var def = type.GetDefinition();
if (def != null && def.ParentAssembly != completion.ctx.CurrentAssembly && !def.IsBrowsable())
return null;
ICompletionData usedType;
var data = Factory.CreateTypeCompletionData(type, showFullName, isInAttributeContext);
var text = data.DisplayText;
if (typeDisplayText.TryGetValue(text, out usedType)) {
usedType.AddOverload(data);
return usedType;
}
typeDisplayText [text] = data;
result.Add(data);
addedTypes[type] = data;
return data;
}
Dictionary<string, List<ICompletionData>> data = new Dictionary<string, List<ICompletionData>> ();
public ICompletionData AddVariable(IVariable variable)
{
if (data.ContainsKey(variable.Name))
return null;
data [variable.Name] = new List<ICompletionData>();
var cd = Factory.CreateVariableCompletionData(variable);
result.Add(cd);
return cd;
}
public ICompletionData AddNamedParameterVariable(IVariable variable)
{
var name = variable.Name + ":";
if (data.ContainsKey(name))
return null;
data [name] = new List<ICompletionData>();
var cd = Factory.CreateVariableCompletionData(variable);
cd.CompletionText += ":";
cd.DisplayText += ":";
result.Add(cd);
return cd;
}
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);
if (member.ParentAssembly != completion.ctx.CurrentAssembly && !member.IsBrowsable ())
return null;
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) {
if (member.SymbolKind == SymbolKind.Field || member.SymbolKind == SymbolKind.Property || member.SymbolKind == SymbolKind.Event)
return null;
var a = member as IEntity;
foreach (var d in existingData) {
if (!(d is IEntityCompletionData))
continue;
var b = ((IEntityCompletionData)d).Entity;
if (a == null || b == null || a.SymbolKind == b.SymbolKind) {
d.AddOverload (newData);
return d;
}
}
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 (IType type)
{
if (type == null)
return null;
if (!completionCategories.ContainsKey (type))
completionCategories [type] = new TypeCompletionCategory (type);
return completionCategories [type];
}
Dictionary<IType, CompletionCategory> completionCategories = new Dictionary<IType, CompletionCategory> ();
class TypeCompletionCategory : CompletionCategory
{
public IType Type {
get;
private set;
}
public TypeCompletionCategory (IType type) : base (type.FullName, null)
{
this.Type = type;
}
public override int CompareTo (CompletionCategory other)
{
var compareCategory = other as TypeCompletionCategory;
if (compareCategory == null)
return -1;
int result;
if (Type.ReflectionName == compareCategory.Type.ReflectionName) {
result = 0;
} else if (Type.GetAllBaseTypes().Any(t => t.ReflectionName == compareCategory.Type.ReflectionName)) {
result = -1;
} else if (compareCategory.Type.GetAllBaseTypes().Any(t => t.ReflectionName == Type.ReflectionName)) {
result = 1;
} else {
var d = Type.GetDefinition ();
var ct = compareCategory.Type.GetDefinition();
if (ct.IsStatic && d.IsStatic) {
result = d.FullName.CompareTo (ct.FullName);
} else if (d.IsStatic) {
result = 1;
}else if (ct.IsStatic) {
result = -1;
} else {
result = 0;
}
}
return result;
}
}
HashSet<IType> addedEnums = new HashSet<IType> ();
public ICompletionData AddEnumMembers (IType resolvedType, CSharpResolver state)
{
if (addedEnums.Contains (resolvedType))
return null;
addedEnums.Add (resolvedType);
var result = AddType(resolvedType, true);
foreach (var field in resolvedType.GetFields ()) {
if (field.IsPublic && (field.IsConst || field.IsStatic)) {
Result.Add(Factory.CreateMemberCompletionData(resolvedType, field));
}
}
return result;
}
}
}