From e24b3330ce4311e070d91e12cabff7adb6516969 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 6 Jan 2013 01:34:45 +0100 Subject: [PATCH] Use SD.Dom for entity context menu. Note: this does not work yet because the DOM implementation is incomplete. --- .../Analysis/UnitTesting/UnitTesting.addin | 2 +- .../ILSpyAddIn/ILSpyAddIn.addin | 2 +- .../Editor/Bookmarks/EntityBookmark.cs | 15 ++- .../Project/ICSharpCode.SharpDevelop.addin | 5 +- .../Commands/SymbolUnderCaretMenuCommand.cs | 33 ++---- .../Project/Util/SharpDevelopExtensions.cs | 110 +++++++++++++++++- .../TopLevelTypeDefinitionModelCollection.cs | 2 +- 7 files changed, 136 insertions(+), 33 deletions(-) diff --git a/src/AddIns/Analysis/UnitTesting/UnitTesting.addin b/src/AddIns/Analysis/UnitTesting/UnitTesting.addin index 4f244995a7..428a3f0785 100644 --- a/src/AddIns/Analysis/UnitTesting/UnitTesting.addin +++ b/src/AddIns/Analysis/UnitTesting/UnitTesting.addin @@ -41,7 +41,7 @@ defaultPosition="Right, Hidden" /> - + diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.addin b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.addin index ea1ec88349..5c7ba7c19f 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.addin +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.addin @@ -17,7 +17,7 @@ - + diff --git a/src/Main/Base/Project/Editor/Bookmarks/EntityBookmark.cs b/src/Main/Base/Project/Editor/Bookmarks/EntityBookmark.cs index c4abf50e82..ac3eb37168 100644 --- a/src/Main/Base/Project/Editor/Bookmarks/EntityBookmark.cs +++ b/src/Main/Base/Project/Editor/Bookmarks/EntityBookmark.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.SharpDevelop.Editor.Bookmarks } } - public const string ContextMenuPath = "/SharpDevelop/ViewContent/TextEditor/EntityContextMenu"; + public const string ContextMenuPath = "/SharpDevelop/EntityContextMenu"; public virtual IImage Image { get { return ClassBrowserIconService.GetIcon(entity); } @@ -54,10 +54,15 @@ namespace ICSharpCode.SharpDevelop.Editor.Bookmarks public virtual void MouseDown(MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) { - var f = SD.AnalyticsMonitor.TrackFeature("ICSharpCode.SharpDevelop.Editor.Bookmarks.EntityBookmark.ShowContextMenu"); - var ctx = MenuService.ShowContextMenu(e.Source as UIElement, entity, ContextMenuPath); - ctx.Closed += delegate { f.EndTracking(); }; - e.Handled = true; + var entityModel = entity.GetModel(); + if (entityModel == null) { + SD.Log.Warn("Could not find model for entity"); + } else { + var f = SD.AnalyticsMonitor.TrackFeature("ICSharpCode.SharpDevelop.Editor.Bookmarks.EntityBookmark.ShowContextMenu"); + var ctx = MenuService.ShowContextMenu(e.Source as UIElement, entityModel, ContextMenuPath); + ctx.Closed += delegate { f.EndTracking(); }; + e.Handled = true; + } } } diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin index 52db5a15a7..0c3b059cfe 100755 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin @@ -1952,12 +1952,13 @@ - + + diff --git a/src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs b/src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs index 49bb604441..9a8517d1dd 100644 --- a/src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs +++ b/src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs @@ -6,6 +6,7 @@ using ICSharpCode.Core; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Parser; @@ -15,9 +16,8 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands /// A menu command that operates on a . /// /// Supports the following types as : - /// - IUnresolvedTypeDefinition (as used by EntityBookmark) - /// - IUnresolvedMember (as used by EntityBookmark) - /// - ResolveResult (so that using the wrong GetEntity overload doesn't cause hard-to-debug problems) + /// - ResolveResult + /// - IEntityModel /// /// If the owner isn't one of the types above, the command operates on the caret position in the current editor. /// @@ -46,8 +46,8 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands { if (owner is ResolveResult) { return (ResolveResult)owner; - } else if (owner is IUnresolvedTypeDefinition || owner is IUnresolvedMember) { - return GetResolveResultFromUnresolvedEntity((IUnresolvedEntity)owner); + } else if (owner is IEntityModel) { + return GetResolveResultFromEntityModel((IEntityModel)owner); } else if (currentEditor != null) { return SD.ParserService.Resolve(currentEditor, currentEditor.Caret.Location); } else { @@ -55,23 +55,14 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands } } - static ResolveResult GetResolveResultFromUnresolvedEntity(IUnresolvedEntity entity) + static ResolveResult GetResolveResultFromEntityModel(IEntityModel entityModel) { - if (entity.UnresolvedFile == null) - return ErrorResolveResult.UnknownError; - ICompilation compilation = SD.ParserService.GetCompilationForFile(FileName.Create(entity.UnresolvedFile.FileName)); - var context = new SimpleTypeResolveContext(compilation.MainAssembly); - if (entity is IUnresolvedMember) { - var member = ((IUnresolvedMember)entity).Resolve(context); - if (member != null) { - return new MemberResolveResult(null, member); - } else { - return ErrorResolveResult.UnknownError; - } - } else { // IUnresolvedTypeDefinition - var type = ((IUnresolvedTypeDefinition)entity).Resolve(context); - return new TypeResolveResult(type); - } + IEntity entity = entityModel.Resolve(); + if (entity is IMember) + return new MemberResolveResult(null, (IMember)entity); + if (entity is ITypeDefinition) + return new TypeResolveResult((ITypeDefinition)entity); + return ErrorResolveResult.UnknownError; } protected static IEntity GetEntity(ResolveResult symbol) diff --git a/src/Main/Base/Project/Util/SharpDevelopExtensions.cs b/src/Main/Base/Project/Util/SharpDevelopExtensions.cs index 7237efd298..5dfcb82b4a 100644 --- a/src/Main/Base/Project/Util/SharpDevelopExtensions.cs +++ b/src/Main/Base/Project/Util/SharpDevelopExtensions.cs @@ -13,13 +13,13 @@ using System.Windows.Controls; using System.Windows.Media; using System.Xml; using System.Xml.Linq; - using ICSharpCode.Core; using ICSharpCode.Core.Presentation; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.Utils; +using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Project; @@ -368,8 +368,114 @@ namespace ICSharpCode.SharpDevelop else return AmbienceService.GetCurrentAmbience(); } + + /// + /// Retrieves the model instance for the given entity. + /// May return null if there is no model for the specified entity. + /// + public static IEntityModel GetModel(this IEntity entity) + { + if (entity == null) + throw new ArgumentNullException("entity"); + + if (entity is ITypeDefinition) + return GetModel((ITypeDefinition)entity); + else if (entity is IMember) + return GetModel((IMember)entity); + else + return null; + } + + /// + /// Retrieves the model instance for the given type definition. + /// May return null if there is no model for the specified type definition. + /// + public static ITypeDefinitionModel GetModel(this ITypeDefinition typeDefinition) + { + if (typeDefinition == null) + throw new ArgumentNullException("typeDefinition"); + + IProject project = typeDefinition.ParentAssembly.GetProject(); + if (project != null) + return project.TypeDefinitionModels[typeDefinition.FullTypeName]; + else + return null; + } + + /// + /// Retrieves the model instance for the given member. + /// May return null if there is no model for the specified member. + /// + public static IMemberModel GetModel(this IMember member) + { + if (member == null) + throw new ArgumentNullException("member"); + + if (member.DeclaringTypeDefinition == null) + return null; + + var snapshot = member.Compilation.SolutionSnapshot as ISolutionSnapshotWithProjectMapping; + if (snapshot == null) + return null; + + ITypeDefinitionModel typeModel = GetModel(member.DeclaringTypeDefinition); + if (typeModel == null) + return null; + + foreach (var memberModel in typeModel.Members) { + if (memberModel.Name == member.Name) { + if (memberModel.Resolve(snapshot) == member.MemberDefinition) { + return memberModel; + } + } + } + return null; + } + + /// + /// Retrieves the model instance the given unresolved entity. + /// + /// The unresolved entity + /// The project in which the entity is defined. + /// If this parameter is null, the project will be determined based on the file name. + /// The entity model if it could be found; or null otherwise. + public static IEntityModel GetModel(this IUnresolvedEntity entity, IProject project = null) + { + if (project == null) { + if (entity.Region.FileName == null || ProjectService.OpenSolution == null) + return null; + project = ProjectService.OpenSolution.FindProjectContainingFile(entity.Region.FileName); + if (project == null) + return null; + } + IUnresolvedTypeDefinition unresolvedTypeDefinition = entity as IUnresolvedTypeDefinition ?? entity.DeclaringTypeDefinition; + if (unresolvedTypeDefinition == null) + return null; + ITypeDefinitionModel typeModel = project.TypeDefinitionModels[unresolvedTypeDefinition.FullTypeName]; + if (entity is IUnresolvedTypeDefinition || typeModel == null) + return typeModel; + + ITypeDefinition typeDefinition = typeModel.Resolve(); + IUnresolvedMember unresolvedMember = entity as IUnresolvedMember; + if (typeDefinition == null || unresolvedMember == null) + return null; + + IMember member = unresolvedMember.Resolve(new SimpleTypeResolveContext(typeDefinition)); + if (member == null) + return null; + var snapshot = member.Compilation.SolutionSnapshot as ISolutionSnapshotWithProjectMapping; + + foreach (var memberModel in typeModel.Members) { + if (memberModel.Name == unresolvedMember.Name) { + if (memberModel.Resolve(snapshot) == member.MemberDefinition) { + return memberModel; + } + } + } + return null; + } #endregion - + #region DPI independence public static Rect TransformToDevice(this Rect rect, Visual visual) { diff --git a/src/Main/SharpDevelop/Dom/TopLevelTypeDefinitionModelCollection.cs b/src/Main/SharpDevelop/Dom/TopLevelTypeDefinitionModelCollection.cs index 5f6cea2cdd..a1168730c3 100644 --- a/src/Main/SharpDevelop/Dom/TopLevelTypeDefinitionModelCollection.cs +++ b/src/Main/SharpDevelop/Dom/TopLevelTypeDefinitionModelCollection.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.SharpDevelop.Dom public ITypeDefinitionModel this[FullTypeName fullTypeName] { get { ITypeDefinitionModel model = this[fullTypeName.TopLevelTypeName]; - for (int i = 0; i < fullTypeName.NestingLevel; i++) { + for (int i = 0; i < fullTypeName.NestingLevel && model != null; i++) { string name = fullTypeName.GetNestedTypeName(i); int atpc = fullTypeName.GetNestedTypeAdditionalTypeParameterCount(i); model = model.GetNestedType(name, atpc);