Browse Source

[Completion] Recognized browsable attributes / streamlined completion

API a bit.
newNRvisualizers
Mike Krüger 14 years ago
parent
commit
bea810b157
  1. 26
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  2. 81
      ICSharpCode.NRefactory.CSharp/Completion/CompletionDataWrapper.cs
  3. 7
      ICSharpCode.NRefactory.CSharp/Completion/ICompletionDataFactory.cs
  4. 144
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/BrowsableAttributeTests.cs
  5. 21
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs
  6. 1
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  7. 8
      ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs

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

@ -543,7 +543,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var wrapper = new CompletionDataWrapper(this); var wrapper = new CompletionDataWrapper(this);
if (currentType != null) { if (currentType != null) {
// bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType); // bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType);
foreach (var method in currentType.Methods) { foreach (var method in ctx.CurrentTypeDefinition.Methods) {
if (MatchDelegate(delegateType, method) /*&& method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) &&*/) { if (MatchDelegate(delegateType, method) /*&& method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) &&*/) {
wrapper.AddMember(method); wrapper.AddMember(method);
// data.SetText (data.CompletionText + ";"); // data.SetText (data.CompletionText + ";");
@ -1200,16 +1200,16 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
wrapper.AddVariable(variable); wrapper.AddVariable(variable);
} }
} }
if (currentMember is IUnresolvedParameterizedMember && !(node is AstType)) { if (state.CurrentMember is IParameterizedMember && !(node is AstType)) {
var param = (IParameterizedMember)currentMember.CreateResolved(ctx); var param = (IParameterizedMember)state.CurrentMember;
foreach (var p in param.Parameters) { foreach (var p in param.Parameters) {
wrapper.AddVariable(p); wrapper.AddVariable(p);
} }
} }
if (currentMember is IUnresolvedMethod) { if (state.CurrentMember is IMethod) {
var method = (IUnresolvedMethod)currentMember; var method = (IMethod)state.CurrentMember;
foreach (var p in method.TypeParameters) { foreach (var p in method.TypeParameters) {
wrapper.AddTypeParameter(p); wrapper.AddTypeParameter(p);
} }
@ -1319,7 +1319,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
{ {
var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly); var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly);
if (currentType != null) { if (currentType != null) {
for (var ct = currentType; ct != null; ct = ct.DeclaringTypeDefinition) { for (var ct = ctx.CurrentTypeDefinition; ct != null; ct = ct.DeclaringTypeDefinition) {
foreach (var nestedType in ct.NestedTypes) { foreach (var nestedType in ct.NestedTypes) {
string name = nestedType.Name; string name = nestedType.Name;
if (IsAttributeContext(node) && name.EndsWith("Attribute") && name.Length > "Attribute".Length) { if (IsAttributeContext(node) && name.EndsWith("Attribute") && name.Length > "Attribute".Length) {
@ -1331,7 +1331,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
continue; continue;
} }
var type = typePred(nestedType.Resolve(ctx)); var type = typePred(nestedType);
if (type != null) { if (type != null) {
var a2 = wrapper.AddType(type, name); var a2 = wrapper.AddType(type, name);
if (a2 != null && callback != null) { if (a2 != null && callback != null) {
@ -1374,8 +1374,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
} }
foreach (var p in currentType.TypeParameters) { if (ctx.CurrentTypeDefinition != null) {
wrapper.AddTypeParameter(p); foreach (var p in ctx.CurrentTypeDefinition.TypeParameters) {
wrapper.AddTypeParameter(p);
}
} }
} }
var scope = ctx.CurrentUsingScope; var scope = ctx.CurrentUsingScope;
@ -1983,7 +1985,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return result; return result;
} }
bool MatchDelegate(IType delegateType, IUnresolvedMethod method) bool MatchDelegate(IType delegateType, IMethod method)
{ {
var delegateMethod = delegateType.GetDelegateInvokeMethod(); var delegateMethod = delegateType.GetDelegateInvokeMethod();
if (delegateMethod == null || delegateMethod.Parameters.Count != method.Parameters.Count) { if (delegateMethod == null || delegateMethod.Parameters.Count != method.Parameters.Count) {
@ -1991,7 +1993,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
for (int i = 0; i < delegateMethod.Parameters.Count; i++) { for (int i = 0; i < delegateMethod.Parameters.Count; i++) {
if (!delegateMethod.Parameters [i].Type.Equals(method.Parameters [i].Type.Resolve(ctx))) { if (!delegateMethod.Parameters [i].Type.Equals(method.Parameters [i].Type)) {
return false; return false;
} }
} }

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

@ -75,31 +75,40 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
HashSet<string> usedTypes = new HashSet<string> (); HashSet<string> usedTypes = new HashSet<string> ();
public ICompletionData AddType(IType type, string shortType) static bool IsBrowsable(IEntity entity)
{ {
if (type == null || string.IsNullOrEmpty(shortType) || usedTypes.Contains(shortType)) var browsable = entity.Attributes.FirstOrDefault(attr => attr.AttributeType.Name == "BrowsableAttribute" && attr.AttributeType.Namespace == "System.ComponentModel");
return null; if (browsable != null && browsable.PositionalArguments.Count == 1 && browsable.PositionalArguments [0].ConstantValue is bool)
if (type.Name == "Void" && type.Namespace == "System") return (bool)browsable.PositionalArguments [0].ConstantValue;
return null;
usedTypes.Add(shortType); var browsableState = entity.Attributes.FirstOrDefault(attr => attr.AttributeType.Name == "EditorBrowsableAttribute" && attr.AttributeType.Namespace == "System.ComponentModel");
var iCompletionData = Factory.CreateTypeCompletionData(type, shortType); if (browsableState != null && browsableState.PositionalArguments.Count == 1) {
result.Add(iCompletionData); try {
return iCompletionData; var state = (System.ComponentModel.EditorBrowsableState)browsableState.PositionalArguments [0].ConstantValue;
return state != System.ComponentModel.EditorBrowsableState.Never;
} catch (Exception) {}
}
return true;
} }
public ICompletionData AddType(IUnresolvedTypeDefinition type, string shortType) public ICompletionData AddType(IType type, string shortType)
{ {
if (type == null || string.IsNullOrEmpty(shortType) || usedTypes.Contains(shortType)) if (type == null || string.IsNullOrEmpty(shortType) || usedTypes.Contains(shortType))
return null; return null;
if (type.Name == "Void" && type.Namespace == "System") if (type.Name == "Void" && type.Namespace == "System")
return null; return null;
var def = type.GetDefinition ();
if (def != null && !IsBrowsable (def))
return null;
usedTypes.Add(shortType); usedTypes.Add(shortType);
var iCompletionData = Factory.CreateTypeCompletionData(type, shortType); var iCompletionData = Factory.CreateTypeCompletionData(type, shortType);
result.Add(iCompletionData); result.Add(iCompletionData);
return iCompletionData; return iCompletionData;
} }
Dictionary<string, List<ICompletionData>> data = new Dictionary<string, List<ICompletionData>> (); Dictionary<string, List<ICompletionData>> data = new Dictionary<string, List<ICompletionData>> ();
public ICompletionData AddVariable(IVariable variable) public ICompletionData AddVariable(IVariable variable)
@ -126,59 +135,25 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return cd; return cd;
} }
public void AddTypeParameter (IUnresolvedTypeParameter variable) public void AddTypeParameter (ITypeParameter variable)
{ {
if (data.ContainsKey (variable.Name)) if (data.ContainsKey (variable.Name))
return; return;
data [variable.Name] = new List<ICompletionData> (); data [variable.Name] = new List<ICompletionData> ();
result.Add (Factory.CreateVariableCompletionData (variable)); result.Add (Factory.CreateVariableCompletionData (variable));
} }
public ICompletionData AddMember (IUnresolvedMember 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.Resolve (completion.ctx));
}
List<ICompletionData> existingData;
data.TryGetValue (memberKey, out existingData);
if (existingData != 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.EntityType == b.EntityType) {
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;
}
public ICompletionData AddMember (IMember member) public ICompletionData AddMember (IMember member)
{ {
var newData = Factory.CreateEntityCompletionData (member); var newData = Factory.CreateEntityCompletionData (member);
// newData.HideExtensionParameter = HideExtensionParameter; if (!IsBrowsable (member))
return null;
string memberKey = newData.DisplayText; string memberKey = newData.DisplayText;
if (memberKey == null) if (memberKey == null)
return null; return null;
if (member is IMember) { if (member is IMember) {
newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition); newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition);
} }

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

@ -32,14 +32,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
{ {
public interface ICompletionDataFactory public interface ICompletionDataFactory
{ {
ICompletionData CreateEntityCompletionData (IUnresolvedEntity entity);
ICompletionData CreateEntityCompletionData (IUnresolvedEntity entity, string text);
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, string shortType);
ICompletionData CreateTypeCompletionData (IUnresolvedTypeDefinition type, string shortType);
/// <summary> /// <summary>
/// Creates a generic completion data. /// Creates a generic completion data.
/// </summary> /// </summary>
@ -58,7 +55,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
ICompletionData CreateVariableCompletionData (IVariable variable); ICompletionData CreateVariableCompletionData (IVariable variable);
ICompletionData CreateVariableCompletionData (IUnresolvedTypeParameter parameter); ICompletionData CreateVariableCompletionData (ITypeParameter parameter);
ICompletionData CreateEventCreationCompletionData (string varName, IType delegateType, IEvent evt, string parameterDefinition, IUnresolvedMember currentMember, IUnresolvedTypeDefinition currentType); ICompletionData CreateEventCreationCompletionData (string varName, IType delegateType, IEvent evt, string parameterDefinition, IUnresolvedMember currentMember, IUnresolvedTypeDefinition currentType);

144
ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/BrowsableAttributeTests.cs

@ -0,0 +1,144 @@
//
// BrowsableAttributeTests.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 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 NUnit.Framework;
using System.Diagnostics;
namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
{
[TestFixture]
public class BrowsableAttributeTests : TestBase
{
[Test()]
public void TestBrowsableClasses ()
{
CompletionDataList provider = CodeCompletionBugTests.CreateProvider (
@"
using System;
using System.ComponentModel;
[Browsable(true)]
class BrowsableTest {}
[Browsable(false)]
class NotBrowsableTest {}
class Test
{
void Test ()
{
$B$
}
}");
Assert.IsNotNull (provider, "provider == null");
Assert.IsNotNull (provider.Find ("BrowsableTest"), "'BrowsableTest' not found.");
Assert.IsNull (provider.Find ("NotBrowsableTest"), "'NotBrowsableTest' found.");
}
[Test()]
public void TestBrowsableMembers ()
{
CompletionDataList provider = CodeCompletionBugTests.CreateProvider (
@"
using System;
using System.ComponentModel;
class Test
{
[Browsable(true)]
int BrowsableTest { get; set; }
[Browsable(false)]
int NotBrowsableTest { get; set; }
void Test ()
{
$B$
}
}");
Assert.IsNotNull (provider, "provider == null");
Assert.IsNotNull (provider.Find ("BrowsableTest"), "'BrowsableTest' not found.");
Assert.IsNull (provider.Find ("NotBrowsableTest"), "'NotBrowsableTest' found.");
}
[Test()]
public void TestEditorBrowsableAttributeClasses ()
{
CompletionDataList provider = CodeCompletionBugTests.CreateProvider (
@"
using System;
using System.ComponentModel;
[EditorBrowsable(EditorBrowsableState.Always)]
class BrowsableTest {}
[EditorBrowsable(EditorBrowsableState.Never)]
class NotBrowsableTest {}
class Test
{
void Test ()
{
$B$
}
}");
Assert.IsNotNull (provider, "provider == null");
Assert.IsNotNull (provider.Find ("BrowsableTest"), "'BrowsableTest' not found.");
Assert.IsNull (provider.Find ("NotBrowsableTest"), "'NotBrowsableTest' found.");
}
[Test()]
public void TestEditorBrowsableAttributeMembers ()
{
CompletionDataList provider = CodeCompletionBugTests.CreateProvider (
@"
using System;
using System.ComponentModel;
class Test
{
[EditorBrowsable(EditorBrowsableState.Always)]
int BrowsableTest { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
int NotBrowsableTest { get; set; }
void Test ()
{
$B$
}
}");
Assert.IsNotNull (provider, "provider == null");
Assert.IsNotNull (provider.Find ("BrowsableTest"), "'BrowsableTest' not found.");
Assert.IsNull (provider.Find ("NotBrowsableTest"), "'NotBrowsableTest' found.");
}
}
}

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

@ -136,15 +136,6 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
return new CompletionData (entity.Name); return new CompletionData (entity.Name);
} }
public ICompletionData CreateEntityCompletionData (ICSharpCode.NRefactory.TypeSystem.IUnresolvedEntity entity, string text)
{
return new CompletionData (text);
}
public ICompletionData CreateTypeCompletionData (ICSharpCode.NRefactory.TypeSystem.IUnresolvedTypeDefinition type, string shortType)
{
return new CompletionData (shortType);
}
public ICompletionData CreateTypeCompletionData (ICSharpCode.NRefactory.TypeSystem.IType type, string shortType) public ICompletionData CreateTypeCompletionData (ICSharpCode.NRefactory.TypeSystem.IType type, string shortType)
{ {
@ -166,7 +157,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
return new CompletionData (variable.Name); return new CompletionData (variable.Name);
} }
public ICompletionData CreateVariableCompletionData (ICSharpCode.NRefactory.TypeSystem.IUnresolvedTypeParameter parameter) public ICompletionData CreateVariableCompletionData (ICSharpCode.NRefactory.TypeSystem.ITypeParameter parameter)
{ {
return new CompletionData (parameter.Name); return new CompletionData (parameter.Name);
} }
@ -199,6 +190,12 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
#endregion #endregion
} }
public static IUnresolvedAssembly SystemAssembly { get { return systemAssembly.Value; } }
static readonly Lazy<IUnresolvedAssembly> systemAssembly = new Lazy<IUnresolvedAssembly>(
delegate {
return new CecilLoader().LoadAssemblyFile(typeof(System.ComponentModel.BrowsableAttribute).Assembly.Location);
});
static CompletionDataList CreateProvider(string text, bool isCtrlSpace) static CompletionDataList CreateProvider(string text, bool isCtrlSpace)
{ {
string parsedText; string parsedText;
@ -215,8 +212,8 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
var doc = new ReadOnlyDocument(editorText); var doc = new ReadOnlyDocument(editorText);
IProjectContent pctx = new CSharpProjectContent(); IProjectContent pctx = new CSharpProjectContent();
pctx = pctx.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore }); pctx = pctx.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore, SystemAssembly });
var compilationUnit = new CSharpParser().Parse(parsedText, "program.cs"); var compilationUnit = new CSharpParser().Parse(parsedText, "program.cs");
compilationUnit.Freeze(); compilationUnit.Freeze();

1
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -274,6 +274,7 @@
<Compile Include="CSharp\CodeActions\ImplementAbstractMembersTest.cs" /> <Compile Include="CSharp\CodeActions\ImplementAbstractMembersTest.cs" />
<Compile Include="CSharp\CodeActions\ExtractFieldTests.cs" /> <Compile Include="CSharp\CodeActions\ExtractFieldTests.cs" />
<Compile Include="CSharp\CodeCompletion\DocumentationContextTests.cs" /> <Compile Include="CSharp\CodeCompletion\DocumentationContextTests.cs" />
<Compile Include="CSharp\CodeCompletion\BrowsableAttributeTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj"> <ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj">

8
ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs

@ -35,12 +35,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
static readonly Lazy<IUnresolvedAssembly> systemCore = new Lazy<IUnresolvedAssembly>( static readonly Lazy<IUnresolvedAssembly> systemCore = new Lazy<IUnresolvedAssembly>(
delegate { delegate {
return new CecilLoader().LoadAssemblyFile(typeof(System.Linq.Enumerable).Assembly.Location); return new CecilLoader().LoadAssemblyFile(typeof(System.Linq.Enumerable).Assembly.Location);
}); });
public static IUnresolvedAssembly Mscorlib { get { return mscorlib.Value; } } public static IUnresolvedAssembly Mscorlib { get { return mscorlib.Value; } }
public static IUnresolvedAssembly SystemCore { get { return systemCore.Value; } } public static IUnresolvedAssembly SystemCore { get { return systemCore.Value; } }
[TestFixtureSetUp] [TestFixtureSetUp]
public void FixtureSetUp() public void FixtureSetUp()
{ {

Loading…
Cancel
Save