diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs index 35f39c0dbb..623303de4b 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.AvalonEdit.AddIn ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.UseFullyQualifiedMemberNames; else ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.ShowParameterList | ConversionFlags.ShowParameterNames; - text = ambience.ConvertEntity(entity); + text = ambience.ConvertEntity(entity, ParserService.GetProject(entity.ProjectContent).TypeResolveContext); image = ClassBrowserIconService.GetIcon(entity); } diff --git a/src/Main/Base/Project/Src/Project/IProject.cs b/src/Main/Base/Project/Src/Project/IProject.cs index 2de1c17c72..d284eb7c9a 100644 --- a/src/Main/Base/Project/Src/Project/IProject.cs +++ b/src/Main/Base/Project/Src/Project/IProject.cs @@ -275,7 +275,7 @@ namespace ICSharpCode.SharpDevelop.Project /// /// This property must not return null. /// If no resolve context is available for this project, it should return a dummy context - /// (e.g. ). + /// (e.g. ). /// /// This member is thread-safe. /// The resulting type resolve context is thread-safe, but repeated locking on every access might be inefficient. diff --git a/src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs b/src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs index a273bf1cb7..b654aa6809 100644 --- a/src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs +++ b/src/Main/Base/Project/Src/Services/AmbienceService/CSharpAmbience.cs @@ -21,9 +21,9 @@ namespace ICSharpCode.SharpDevelop public ConversionFlags ConversionFlags { get; set; } #region ConvertEntity - public string ConvertEntity(IEntity e) + public string ConvertEntity(IEntity e, ITypeResolveContext context) { - using (var ctx = ParserService.CurrentTypeResolveContext.Synchronize()) { + using (var ctx = context.Synchronize()) { StringWriter writer = new StringWriter(); switch (e.EntityType) { @@ -33,7 +33,7 @@ namespace ICSharpCode.SharpDevelop ConvertTypeDeclaration((ITypeDefinition)e, ctx, writer); break; case EntityType.Field: - + ConvertField((IField)e, ctx, writer); break; case EntityType.Property: @@ -64,6 +64,20 @@ namespace ICSharpCode.SharpDevelop } } + void ConvertField(IField field, ISynchronizedTypeResolveContext ctx, StringWriter writer) + { + TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder(ctx); + astBuilder.ShowModifiers = (ConversionFlags & ConversionFlags.ShowModifiers) == ConversionFlags.ShowModifiers; + astBuilder.ShowAccessibility = (ConversionFlags & ConversionFlags.ShowAccessibility) == ConversionFlags.ShowAccessibility; + FieldDeclaration fieldDecl = (FieldDeclaration)astBuilder.ConvertEntity(field); + PrintModifiers(fieldDecl.Modifiers, writer); + if ((ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) { + writer.Write(ConvertType(field.Type, ctx)); + writer.Write(' '); + } + WriteFieldDeclarationName(field, ctx, writer); + } + void ConvertTypeDeclaration(ITypeDefinition typeDef, ITypeResolveContext ctx, StringWriter writer) { TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder(ctx); @@ -88,7 +102,7 @@ namespace ICSharpCode.SharpDevelop default: throw new Exception("Invalid value for ClassType"); } - writer.Write(" "); + writer.Write(' '); } WriteTypeDeclarationName(typeDef, ctx, writer); } @@ -109,6 +123,15 @@ namespace ICSharpCode.SharpDevelop } } + void WriteFieldDeclarationName(IField field, ITypeResolveContext ctx, StringWriter writer) + { + if ((ConversionFlags & ConversionFlags.UseFullyQualifiedMemberNames) == ConversionFlags.UseFullyQualifiedMemberNames) { + writer.Write(ConvertType(field.DeclaringType)); + writer.Write('.'); + } + writer.Write(field.Name); + } + void PrintNode(AstNode node, StringWriter writer) { node.AcceptVisitor(CreatePrinter(writer), null); @@ -124,15 +147,15 @@ namespace ICSharpCode.SharpDevelop foreach (var m in CSharpModifierToken.AllModifiers) { if ((modifiers & m) == m) { writer.Write(CSharpModifierToken.GetModifierName(m)); - writer.Write(" "); + writer.Write(' '); } } } #endregion - public string ConvertVariable(IVariable v) + public string ConvertVariable(IVariable v, ITypeResolveContext context) { - using (var ctx = ParserService.CurrentTypeResolveContext.Synchronize()) { + using (var ctx = context.Synchronize()) { TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder(ctx); AstNode astNode = astBuilder.ConvertVariable(v); CSharpFormattingOptions formatting = new CSharpFormattingOptions(); @@ -154,6 +177,16 @@ namespace ICSharpCode.SharpDevelop } } + public string ConvertType(ITypeReference type, ITypeResolveContext context) + { + TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder(context); + AstType astType = astBuilder.ConvertTypeReference(type); + CSharpFormattingOptions formatting = new CSharpFormattingOptions(); + StringWriter writer = new StringWriter(); + astType.AcceptVisitor(new OutputVisitor(writer, formatting), null); + return writer.ToString(); + } + public string WrapAttribute(string attribute) { return "[" + attribute + "]"; diff --git a/src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs b/src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs index fe4aadf64f..bb2e2f80e0 100644 --- a/src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs +++ b/src/Main/Base/Project/Src/Services/AmbienceService/IAmbience.cs @@ -69,9 +69,10 @@ namespace ICSharpCode.SharpDevelop set; } - string ConvertEntity(IEntity e); + string ConvertEntity(IEntity e, ITypeResolveContext context); string ConvertType(IType type); - string ConvertVariable(IVariable variable); + string ConvertType(ITypeReference type, ITypeResolveContext context); + string ConvertVariable(IVariable variable, ITypeResolveContext context); string WrapAttribute(string attribute); string WrapComment(string comment); diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs index ff10f21af9..2d5f39a9f8 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs @@ -341,9 +341,11 @@ namespace ICSharpCode.SharpDevelop.Debugging StringBuilder b = new StringBuilder(); if (rr.IsParameter) b.Append("parameter "); + else if (rr.Variable.IsConst) + b.Append("constant "); else b.Append("local variable "); - b.Append(ambience.ConvertVariable(rr.Variable)); + b.Append(ambience.ConvertVariable(rr.Variable, ParserService.CurrentTypeResolveContext)); if (!rr.IsCompileTimeConstant && currentDebugger != null) { string currentValue = currentDebugger.GetValueAsString(e, rr); if (currentValue != null) { @@ -378,7 +380,7 @@ namespace ICSharpCode.SharpDevelop.Debugging bool tryDisplayValue = false; debuggerCanShowValue = false; StringBuilder text = new StringBuilder(); - text.Append(ambience.ConvertEntity(member)); + text.Append(ambience.ConvertEntity(member, ParserService.CurrentTypeResolveContext)); tryDisplayValue = ((member is IField && !((IField)member).IsConst) || member is IProperty); if (tryDisplayValue && currentDebugger != null) { diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHelper.cs b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHelper.cs index 0734f3402e..7c55a7c847 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHelper.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHelper.cs @@ -65,7 +65,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring protected ContextActionViewModel MakeGoToClassAction(ITypeDefinition @class, ObservableCollection childActions) { return new ContextActionViewModel { - Action = new GoToClassAction(@class, this.LabelAmbience.ConvertEntity(@class)), + Action = new GoToClassAction(@class, this.LabelAmbience.ConvertEntity(@class, ParserService.CurrentTypeResolveContext)), Image = ClassBrowserIconService.GetIcon(@class).ImageSource, Comment = string.Format("(in {0})", @class.Namespace), ChildActions = childActions diff --git a/src/Main/Base/Test/CSharpAmbienceTests.cs b/src/Main/Base/Test/CSharpAmbienceTests.cs index 8fc2c05314..c92da676f1 100644 --- a/src/Main/Base/Test/CSharpAmbienceTests.cs +++ b/src/Main/Base/Test/CSharpAmbienceTests.cs @@ -3,8 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using ICSharpCode.Core; using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.SharpDevelop.Parser; using NUnit.Framework; @@ -14,21 +16,27 @@ namespace ICSharpCode.SharpDevelop.Tests public class CSharpAmbienceTests { IProjectContent mscorlib; + IProjectContent myLib; + CompositeTypeResolveContext compositeContext; CSharpAmbience ambience; - [SetUp] - public void Setup() + public CSharpAmbienceTests() { ambience = new CSharpAmbience(); mscorlib = AssemblyParserService.GetAssembly(FileName.Create(typeof(object).Assembly.Location)); + var loader = new CecilLoader(); + loader.IncludeInternalMembers = true; + myLib = loader.LoadAssemblyFile(typeof(CSharpAmbienceTests).Assembly.Location); + compositeContext = new CompositeTypeResolveContext(new[] { mscorlib, myLib }); } + #region ITypeDefinition tests [Test] public void GenericType() { var typeDef = mscorlib.GetTypeDefinition(typeof(Dictionary<,>)); ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("System.Collections.Generic.Dictionary", result); } @@ -38,7 +46,7 @@ namespace ICSharpCode.SharpDevelop.Tests { var typeDef = mscorlib.GetTypeDefinition(typeof(Dictionary<,>)); ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("Dictionary", result); } @@ -48,7 +56,7 @@ namespace ICSharpCode.SharpDevelop.Tests { var typeDef = mscorlib.GetTypeDefinition(typeof(Object)); ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("System.Object", result); } @@ -58,7 +66,7 @@ namespace ICSharpCode.SharpDevelop.Tests { var typeDef = mscorlib.GetTypeDefinition(typeof(Object)); ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.UseFullyQualifiedMemberNames); - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("public class Object", result); } @@ -68,7 +76,7 @@ namespace ICSharpCode.SharpDevelop.Tests { var typeDef = mscorlib.GetTypeDefinition(typeof(Object)); ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowModifiers | ConversionFlags.ShowAccessibility); - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("class Object", result); } @@ -78,7 +86,7 @@ namespace ICSharpCode.SharpDevelop.Tests { var typeDef = mscorlib.GetTypeDefinition(typeof(List<>)); ambience.ConversionFlags = ConversionFlags.All; - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("public class System.Collections.Generic.List", result); } @@ -88,7 +96,7 @@ namespace ICSharpCode.SharpDevelop.Tests { var typeDef = mscorlib.GetTypeDefinition(typeof(Object)); ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("Object", result); } @@ -98,7 +106,7 @@ namespace ICSharpCode.SharpDevelop.Tests { var typeDef = mscorlib.GetTypeDefinition(typeof(List<>.Enumerator)); ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("System.Collections.Generic.List.Enumerator", result); } @@ -108,9 +116,55 @@ namespace ICSharpCode.SharpDevelop.Tests { var typeDef = mscorlib.GetTypeDefinition(typeof(List<>.Enumerator)); ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList; - string result = ambience.ConvertEntity(typeDef); + string result = ambience.ConvertEntity(typeDef, mscorlib); Assert.AreEqual("List.Enumerator", result); } + #endregion + + #region IField tests + [Test] + public void SimpleField() + { + var field = typeof(CSharpAmbienceTests.MyClass).ToTypeReference().Resolve(myLib) + .GetDefinition().Fields.Single(f => f.Name == "test"); + ambience.ConversionFlags = ConversionFlags.All; + string result = ambience.ConvertEntity(field, compositeContext); + + Assert.AreEqual("private int ICSharpCode.SharpDevelop.Tests.CSharpAmbienceTests.MyClass.test", result); + } + + [Test] + public void SimpleConstField() + { + var field = typeof(CSharpAmbienceTests.MyClass).ToTypeReference().Resolve(myLib) + .GetDefinition().Fields.Single(f => f.Name == "TEST"); + ambience.ConversionFlags = ConversionFlags.All; + string result = ambience.ConvertEntity(field, compositeContext); + + Assert.AreEqual("private const int ICSharpCode.SharpDevelop.Tests.CSharpAmbienceTests.MyClass.TEST", result); + } + + [Test] + public void SimpleFieldWithoutModifiers() + { + var field = typeof(CSharpAmbienceTests.MyClass).ToTypeReference().Resolve(myLib) + .GetDefinition().Fields.Single(f => f.Name == "test"); + ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.UseFullyQualifiedMemberNames | ConversionFlags.ShowModifiers | ConversionFlags.ShowAccessibility); + string result = ambience.ConvertEntity(field, compositeContext); + + Assert.AreEqual("int test", result); + } + #endregion + + #region Test types + #pragma warning disable 169 + + class MyClass + { + const int TEST = 0; + int test; + } + #endregion } }