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

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

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

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

@ -35,7 +35,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -35,7 +35,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
ICompletionData CreateEntityCompletionData (IEntity entity);
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>
/// Creates a generic completion data.

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

@ -37,6 +37,8 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem; @@ -37,6 +37,8 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
{
@ -68,6 +70,14 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion @@ -68,6 +70,14 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
class TestFactory
: ICompletionDataFactory
{
readonly TypeSystemAstBuilder builder;
public TestFactory(CSharpResolver state)
{
Console.WriteLine ("ct:"+state.CurrentTypeDefinition);
builder = new TypeSystemAstBuilder(state);
}
class CompletionData
: ICompletionData
{
@ -143,11 +153,22 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion @@ -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)
{
return new CompletionData (title);
@ -251,7 +272,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion @@ -251,7 +272,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
}
var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);
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.FormattingPolicy = FormattingOptionsFactory.CreateMono();
@ -283,7 +304,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion @@ -283,7 +304,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
var cmp = pctx.CreateCompilation();
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.FormattingPolicy = FormattingOptionsFactory.CreateMono ();
return Tuple.Create (doc, engine);

Loading…
Cancel
Save