Browse Source

[Completion] Refactored the completion data factory (shortType no

longer required - should be done lazy in the GUI).
newNRvisualizers
Mike Krüger 14 years ago
parent
commit
c829bd6c27
  1. 69
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  2. 28
      ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs
  3. 9
      ICSharpCode.NRefactory.CSharp/Completion/ICompletionDataFactory.cs
  4. 29
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs

69
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -1308,7 +1308,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
return false; return false;
} }
void AddTypesAndNamespaces(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, Func<IType, IType> typePred = null, Predicate<IMember> memberPred = null, Action<ICompletionData, IType> callback = null) void AddTypesAndNamespaces(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, Func<IType, IType> typePred = null, Predicate<IMember> memberPred = null, Action<ICompletionData, IType> callback = null)
{ {
var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly); var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly);
@ -1316,21 +1316,17 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (currentType != null) { if (currentType != null) {
for (var ct = ctx.CurrentTypeDefinition; ct != null; ct = ct.DeclaringTypeDefinition) { for (var ct = ctx.CurrentTypeDefinition; ct != null; ct = ct.DeclaringTypeDefinition) {
foreach (var nestedType in ct.GetNestedTypes ()) { foreach (var nestedType in ct.GetNestedTypes ()) {
string name = nestedType.Name;
if (!lookup.IsAccessible (nestedType.GetDefinition (), true)) if (!lookup.IsAccessible (nestedType.GetDefinition (), true))
continue; continue;
if (IsAttributeContext(node) && name.EndsWith("Attribute") && name.Length > "Attribute".Length) {
name = name.Substring(0, name.Length - "Attribute".Length);
}
if (typePred == null) { if (typePred == null) {
wrapper.AddType(nestedType, name); wrapper.AddType(nestedType, false, IsAttributeContext(node));
continue; continue;
} }
var type = typePred(nestedType); var type = typePred(nestedType);
if (type != null) { if (type != null) {
var a2 = wrapper.AddType(type, name); var a2 = wrapper.AddType(type, false, IsAttributeContext(node));
if (a2 != null && callback != null) { if (a2 != null && callback != null) {
callback(a2, type); callback(a2, type);
} }
@ -1392,11 +1388,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
IType addType = typePred != null ? typePred(type) : type; IType addType = typePred != null ? typePred(type) : type;
if (addType != null) { if (addType != null) {
string name = type.Name; var a = wrapper.AddType(addType, false, IsAttributeContext(node));
if (IsAttributeContext(node) && name.EndsWith("Attribute") && name.Length > "Attribute".Length) {
name = name.Substring(0, name.Length - "Attribute".Length);
}
var a = wrapper.AddType(addType, name);
if (a != null && callback != null) { if (a != null && callback != null) {
callback(a, type); callback(a, type);
} }
@ -1409,7 +1401,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
continue; continue;
IType addType = typePred != null ? typePred(type) : type; IType addType = typePred != null ? typePred(type) : type;
if (addType != null) { if (addType != null) {
var a2 = wrapper.AddType(addType, addType.Name); var a2 = wrapper.AddType(addType, false);
if (a2 != null && callback != null) { if (a2 != null && callback != null) {
callback(a2, type); callback(a2, type);
} }
@ -1773,7 +1765,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
new [] { hintType } new [] { hintType }
); );
if (inferedType != SpecialType.UnknownType) { if (inferedType != SpecialType.UnknownType) {
var newType = wrapper.AddType(inferedType, amb.ConvertType(inferedType)); var newType = wrapper.AddType(inferedType, true);
if (newType != null) { if (newType != null) {
newType.CompletionCategory = inferredTypesCategory; newType.CompletionCategory = inferredTypesCategory;
} }
@ -1782,8 +1774,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return t; return t;
}; };
if (!(hintType.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array)) { if (!(hintType.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array)) {
DefaultCompletionString = GetShortType(hintType, GetState()); var hint = wrapper.AddType(hintType, true);
var hint = wrapper.AddType(hintType, DefaultCompletionString); DefaultCompletionString = hint.DisplayText;
if (hint != null) { if (hint != null) {
hint.CompletionCategory = derivedTypesCategory; hint.CompletionCategory = derivedTypesCategory;
} }
@ -1792,11 +1784,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var arg = ((ParameterizedType)hintType).TypeArguments.FirstOrDefault(); var arg = ((ParameterizedType)hintType).TypeArguments.FirstOrDefault();
if (arg.Kind != TypeKind.TypeParameter) { if (arg.Kind != TypeKind.TypeParameter) {
var array = new ArrayType (ctx.Compilation, arg, 1); var array = new ArrayType (ctx.Compilation, arg, 1);
wrapper.AddType(array, amb.ConvertType(array)); wrapper.AddType(array, true);
} }
} }
} else { } else {
var hint = wrapper.AddType(hintType, DefaultCompletionString); var hint = wrapper.AddType(hintType, true);
if (hint != null) { if (hint != null) {
DefaultCompletionString = hint.DisplayText; DefaultCompletionString = hint.DisplayText;
hint.CompletionCategory = derivedTypesCategory; hint.CompletionCategory = derivedTypesCategory;
@ -2163,14 +2155,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var nr = (NamespaceResolveResult)resolveResult; var nr = (NamespaceResolveResult)resolveResult;
if (!(resolvedNode.Parent is UsingDeclaration || resolvedNode.Parent != null && resolvedNode.Parent.Parent is UsingDeclaration)) { if (!(resolvedNode.Parent is UsingDeclaration || resolvedNode.Parent != null && resolvedNode.Parent.Parent is UsingDeclaration)) {
foreach (var cl in nr.Namespace.Types) { foreach (var cl in nr.Namespace.Types) {
string name = cl.Name;
if (hintType != null && hintType.Kind != TypeKind.Array && cl.Kind == TypeKind.Interface) { if (hintType != null && hintType.Kind != TypeKind.Array && cl.Kind == TypeKind.Interface) {
continue; continue;
} }
if (IsAttributeContext(resolvedNode) && name.EndsWith("Attribute") && name.Length > "Attribute".Length) { result.AddType(cl, false, IsAttributeContext(resolvedNode));
name = name.Substring(0, name.Length - "Attribute".Length);
}
result.AddType(cl, name);
} }
} }
foreach (var ns in nr.Namespace.ChildNamespaces) { foreach (var ns in nr.Namespace.ChildNamespaces) {
@ -2182,7 +2170,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (hintType != null && hintType.Kind != TypeKind.Array && nested.Kind == TypeKind.Interface) { if (hintType != null && hintType.Kind != TypeKind.Array && nested.Kind == TypeKind.Interface) {
continue; continue;
} }
result.AddType(nested, nested.Name); result.AddType(nested, false);
} }
} }
return result.Result; return result.Result;
@ -2191,7 +2179,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
IEnumerable<ICompletionData> CreateTypeList() IEnumerable<ICompletionData> CreateTypeList()
{ {
foreach (var cl in Compilation.RootNamespace.Types) { foreach (var cl in Compilation.RootNamespace.Types) {
yield return factory.CreateTypeCompletionData(cl, cl.Name); yield return factory.CreateTypeCompletionData(cl, false, false);
} }
foreach (var ns in Compilation.RootNamespace.ChildNamespaces) { foreach (var ns in Compilation.RootNamespace.ChildNamespaces) {
@ -2261,33 +2249,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// } // }
return result.Result; return result.Result;
} }
string GetShortType(IType type, CSharpResolver state)
{
var builder = new TypeSystemAstBuilder(state);
var dt = state.CurrentTypeDefinition;
var declaring = type.DeclaringType != null ? type.DeclaringType.GetDefinition() : null;
if (declaring != null) {
while (dt != null) {
if (dt.Equals(declaring)) {
builder.AlwaysUseShortTypeNames = true;
break;
}
dt = dt.DeclaringTypeDefinition;
}
}
var shortType = builder.ConvertType(type);
return shortType.GetText(FormattingPolicy);
}
void AddEnumMembers(CompletionDataWrapper completionList, IType resolvedType, CSharpResolver state) void AddEnumMembers(CompletionDataWrapper completionList, IType resolvedType, CSharpResolver state)
{ {
if (resolvedType.Kind != TypeKind.Enum) { if (resolvedType.Kind != TypeKind.Enum) {
return; return;
} }
string typeString = GetShortType(resolvedType, state); completionList.AddEnumMembers(resolvedType, state);
completionList.AddEnumMembers(resolvedType, state, typeString); DefaultCompletionString = resolvedType.Name;
DefaultCompletionString = typeString;
} }
IEnumerable<ICompletionData> CreateCompletionData(TextLocation location, ResolveResult resolveResult, AstNode resolvedNode, CSharpResolver state, Func<IType, IType> typePred = null) IEnumerable<ICompletionData> CreateCompletionData(TextLocation location, ResolveResult resolveResult, AstNode resolvedNode, CSharpResolver state, Func<IType, IType> typePred = null)
@ -2310,7 +2279,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
continue; continue;
IType addType = typePred != null ? typePred(cl) : cl; IType addType = typePred != null ? typePred(cl) : cl;
if (addType != null) if (addType != null)
namespaceContents.AddType(addType, addType.Name); namespaceContents.AddType(addType, false);
} }
foreach (var ns in nr.Namespace.ChildNamespaces) { foreach (var ns in nr.Namespace.ChildNamespaces) {
@ -2441,7 +2410,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
result.AddMember ((IMember)member); result.AddMember ((IMember)member);
} else { } else {
if (resolveResult is TypeResolveResult || includeStaticMembers) if (resolveResult is TypeResolveResult || includeStaticMembers)
result.AddType ((IType)member, member.Name); result.AddType ((IType)member, false);
} }
} }
} }
@ -2452,7 +2421,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
continue; continue;
IType addType = typePred != null ? typePred(nested) : nested; IType addType = typePred != null ? typePred(nested) : nested;
if (addType != null) if (addType != null)
result.AddType(addType, addType.Name); result.AddType(addType, false);
} }
} else { } else {

28
ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs

@ -80,12 +80,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
result.Add (Factory.CreateLiteralCompletionData (alias)); result.Add (Factory.CreateLiteralCompletionData (alias));
} }
Dictionary<string, ICompletionData> usedTypes = new Dictionary<string, ICompletionData> (); Dictionary<IType, ICompletionData> usedTypes = new Dictionary<IType, ICompletionData> ();
public ICompletionData AddType(IType type, string shortType) public ICompletionData AddType(IType type, bool showFullName, bool isInAttributeContext = false)
{ {
if (type == null || string.IsNullOrEmpty(shortType)) if (type == null)
return null; throw new ArgumentNullException("type");
if (type.Name == "Void" && type.Namespace == "System") if (type.Name == "Void" && type.Namespace == "System")
return null; return null;
@ -93,12 +93,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (def != null && def.ParentAssembly != completion.ctx.CurrentAssembly && !def.IsBrowsable()) if (def != null && def.ParentAssembly != completion.ctx.CurrentAssembly && !def.IsBrowsable())
return null; return null;
ICompletionData usedType; ICompletionData usedType;
if (usedTypes.TryGetValue (shortType, out usedType)) { if (usedTypes.TryGetValue (type, out usedType)) {
usedType.AddOverload (Factory.CreateTypeCompletionData(type, shortType)); usedType.AddOverload (Factory.CreateTypeCompletionData(type, showFullName, isInAttributeContext));
return usedType; return usedType;
} }
var iCompletionData = Factory.CreateTypeCompletionData(type, shortType); var iCompletionData = Factory.CreateTypeCompletionData(type, showFullName, isInAttributeContext);
usedTypes[shortType] = iCompletionData; usedTypes[type] = iCompletionData;
result.Add(iCompletionData); result.Add(iCompletionData);
return iCompletionData; return iCompletionData;
} }
@ -214,21 +214,15 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
HashSet<IType> addedEnums = new HashSet<IType> (); HashSet<IType> addedEnums = new HashSet<IType> ();
public void AddEnumMembers (IType resolvedType, CSharpResolver state, string typeString) public void AddEnumMembers (IType resolvedType, CSharpResolver state)
{ {
if (addedEnums.Contains (resolvedType)) if (addedEnums.Contains (resolvedType))
return; return;
addedEnums.Add (resolvedType); addedEnums.Add (resolvedType);
if (typeString.Contains(".")) { AddType(resolvedType, true);
AddType(resolvedType, typeString);
}
foreach (var field in resolvedType.GetFields ()) { foreach (var field in resolvedType.GetFields ()) {
if (field.IsPublic && (field.IsConst || field.IsStatic)) { if (field.IsPublic && (field.IsConst || field.IsStatic)) {
Result.Add(Factory.CreateEntityCompletionData( Result.Add(Factory.CreateMemberCompletionData(resolvedType, field));
field,
typeString + "." + field.Name
)
);
} }
} }
} }

9
ICSharpCode.NRefactory.CSharp/Completion/ICompletionDataFactory.cs

@ -35,7 +35,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
ICompletionData CreateEntityCompletionData (IEntity entity); ICompletionData CreateEntityCompletionData (IEntity entity);
ICompletionData CreateEntityCompletionData (IEntity entity, string text); ICompletionData CreateEntityCompletionData (IEntity entity, string text);
ICompletionData CreateTypeCompletionData (IType type, string shortType); ICompletionData CreateTypeCompletionData (IType type, bool showFullName, bool isInAttributeContext);
/// <summary>
/// Creates the member completion data.
/// Form: Type.Member
/// Used for generating enum members Foo.A, Foo.B where the enum 'Foo' is valid.
/// </summary>
ICompletionData CreateMemberCompletionData(IType type, IEntity member);
/// <summary> /// <summary>
/// Creates a generic completion data. /// Creates a generic completion data.

29
ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs

@ -37,6 +37,8 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework; using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace ICSharpCode.NRefactory.CSharp.CodeCompletion namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
{ {
@ -68,6 +70,14 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
class TestFactory class TestFactory
: ICompletionDataFactory : ICompletionDataFactory
{ {
readonly TypeSystemAstBuilder builder;
public TestFactory(CSharpResolver state)
{
Console.WriteLine ("ct:"+state.CurrentTypeDefinition);
builder = new TypeSystemAstBuilder(state);
}
class CompletionData class CompletionData
: ICompletionData : ICompletionData
{ {
@ -143,11 +153,22 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
} }
public ICompletionData CreateTypeCompletionData (ICSharpCode.NRefactory.TypeSystem.IType type, string shortType) public ICompletionData CreateTypeCompletionData (ICSharpCode.NRefactory.TypeSystem.IType type, bool fullName, bool isInAttributeContext)
{ {
return new CompletionData (shortType); string name = fullName ? builder.ConvertType(type).GetText() : type.Name;
if (isInAttributeContext && name.EndsWith("Attribute") && name.Length > "Attribute".Length) {
name = name.Substring(0, name.Length - "Attribute".Length);
}
return new CompletionData (name);
}
public ICompletionData CreateMemberCompletionData(IType type, IEntity member)
{
string name = builder.ConvertType(type).GetText();
Console.WriteLine("name:"+name);
return new CompletionData (name + "."+ member.Name);
} }
public ICompletionData CreateLiteralCompletionData (string title, string description, string insertText) public ICompletionData CreateLiteralCompletionData (string title, string description, string insertText)
{ {
return new CompletionData (title); return new CompletionData (title);
@ -251,7 +272,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
} }
var mb = new DefaultCompletionContextProvider(doc, unresolvedFile); var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);
mb.AddSymbol ("TEST"); mb.AddSymbol ("TEST");
var engine = new CSharpCompletionEngine(doc, mb, new TestFactory(), pctx, rctx); var engine = new CSharpCompletionEngine(doc, mb, new TestFactory(new CSharpResolver (rctx)), pctx, rctx);
engine.EolMarker = Environment.NewLine; engine.EolMarker = Environment.NewLine;
engine.FormattingPolicy = FormattingOptionsFactory.CreateMono(); engine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
@ -283,7 +304,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
var cmp = pctx.CreateCompilation(); var cmp = pctx.CreateCompilation();
var mb = new DefaultCompletionContextProvider(doc, unresolvedFile); var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);
var engine = new CSharpCompletionEngine (doc, mb, new TestFactory (), pctx, new CSharpTypeResolveContext (cmp.MainAssembly)); var engine = new CSharpCompletionEngine (doc, mb, new TestFactory (new CSharpResolver (new CSharpTypeResolveContext (cmp.MainAssembly))), pctx, new CSharpTypeResolveContext (cmp.MainAssembly));
engine.EolMarker = Environment.NewLine; engine.EolMarker = Environment.NewLine;
engine.FormattingPolicy = FormattingOptionsFactory.CreateMono (); engine.FormattingPolicy = FormattingOptionsFactory.CreateMono ();
return Tuple.Create (doc, engine); return Tuple.Create (doc, engine);

Loading…
Cancel
Save