From 0f47b3c711730a876a862cb59cb80f11fc708f71 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 20 Aug 2013 18:21:47 +0200 Subject: [PATCH] add support for Assembly References to IAssemblyModel --- .../Pads/ClassBrowserSupport.cs | 22 ++++++++++++--- .../Dom/ClassBrowser/ClassBrowserTreeView.cs | 21 ++++++++++----- .../Project/Dom/ClassBrowser/IClassBrowser.cs | 8 ++---- .../Dom/ClassBrowser/WorkspaceModel.cs | 12 +++++++++ .../Dom/ClassBrowser/WorkspaceTreeNode.cs | 13 +++------ src/Main/Base/Project/Dom/IAssemblyModel.cs | 5 ++++ .../Project/Dom/ModelFactoryExtensions.cs | 27 +++---------------- .../Project/Parser/ProjectContentContainer.cs | 2 +- .../Project/Src/Project/CompilableProject.cs | 15 +++++++++++ src/Main/SharpDevelop/Dom/AssemblyModel.cs | 5 +++- .../Dom/ClassBrowser/ClassBrowserPad.cs | 15 +++++++---- 11 files changed, 90 insertions(+), 55 deletions(-) diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ClassBrowserSupport.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ClassBrowserSupport.cs index 3c7ea4ca64..ca3ce52d48 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ClassBrowserSupport.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ClassBrowserSupport.cs @@ -10,6 +10,7 @@ using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Dom.ClassBrowser; using System.Linq; +using ICSharpCode.SharpDevelop.Parser; namespace ICSharpCode.SharpDevelop.Gui.Pads { @@ -81,6 +82,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads DebuggerModuleModel model = new DebuggerModuleModel(e.Module); moduleModels.Add(model); Assemblies.Add(model.AssemblyModel); + foreach (var module in moduleModels) + module.UpdateReferences(); } void ModuleUnloaded(object sender, ModuleEventArgs e) @@ -89,6 +92,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads if (deletedModel != null) { moduleModels.Remove(deletedModel); Assemblies.Remove(deletedModel.AssemblyModel); + foreach (var module in moduleModels) + module.UpdateReferences(); } } @@ -181,14 +186,23 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } + public void UpdateReferences() + { + var model = assemblyModel as IUpdateableAssemblyModel; + if (model == null) return; + // this could be totally wrong ... + model.References = module.AppDomain.Compilation.Assemblies.Where(a => a.FullAssemblyName != module.UnresolvedAssembly.FullAssemblyName).Select(a => new DomAssemblyName(a.FullAssemblyName)).ToList(); + } + static IAssemblyModel CreateAssemblyModel(Module module) { // references?? IEntityModelContext context = new AssemblyEntityModelContext(module.Assembly.UnresolvedAssembly); - IAssemblyModel model = SD.GetRequiredService().CreateAssemblyModel(context); - if (model is IUpdateableAssemblyModel) { - ((IUpdateableAssemblyModel)model).Update(EmptyList.Instance, module.Assembly.TopLevelTypeDefinitions.SelectMany(td => td.Parts).ToList()); - } + IUpdateableAssemblyModel model = SD.GetRequiredService().CreateAssemblyModel(context); + var types = module.Assembly.TopLevelTypeDefinitions.SelectMany(td => td.Parts).ToList(); + model.AssemblyName = module.UnresolvedAssembly.AssemblyName; + model.Update(EmptyList.Instance, types); + return model; } } diff --git a/src/Main/Base/Project/Dom/ClassBrowser/ClassBrowserTreeView.cs b/src/Main/Base/Project/Dom/ClassBrowser/ClassBrowserTreeView.cs index 792804a706..009702680f 100644 --- a/src/Main/Base/Project/Dom/ClassBrowser/ClassBrowserTreeView.cs +++ b/src/Main/Base/Project/Dom/ClassBrowser/ClassBrowserTreeView.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Windows.Controls; +using ICSharpCode.Core; using ICSharpCode.TreeView; namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser @@ -11,14 +12,21 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser public class ClassBrowserTreeView : SharpTreeView, IClassBrowserTreeView { #region IClassBrowser implementation + + WorkspaceModel workspace; public ICollection AssemblyLists { - get { return ((WorkspaceTreeNode)Root).AssemblyLists; } + get { return workspace.AssemblyLists; } } public IAssemblyList MainAssemblyList { - get { return ((WorkspaceTreeNode)Root).AssemblyList; } - set { ((WorkspaceTreeNode)Root).AssemblyList = value; } + get { return workspace.MainAssemblyList; } + set { workspace.MainAssemblyList = value; } + } + + public IAssemblyModel FindAssemblyModel(FileName fileName) + { + return workspace.FindAssemblyModel(fileName); } #endregion @@ -26,12 +34,13 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser public ClassBrowserTreeView() { WorkspaceTreeNode root = new WorkspaceTreeNode(); + this.workspace = root.Workspace; ClassBrowserTreeView instance = this; - root.AssemblyLists.CollectionChanged += delegate { - instance.ShowRoot = root.AssemblyLists.Count > 0; + root.Workspace.AssemblyLists.CollectionChanged += delegate { + instance.ShowRoot = root.Workspace.AssemblyLists.Count > 0; }; root.PropertyChanged += delegate { - instance.ShowRoot = root.AssemblyLists.Count > 0; + instance.ShowRoot = root.Workspace.AssemblyLists.Count > 0; }; this.Root = root; } diff --git a/src/Main/Base/Project/Dom/ClassBrowser/IClassBrowser.cs b/src/Main/Base/Project/Dom/ClassBrowser/IClassBrowser.cs index b326dc5c02..2174693bb2 100644 --- a/src/Main/Base/Project/Dom/ClassBrowser/IClassBrowser.cs +++ b/src/Main/Base/Project/Dom/ClassBrowser/IClassBrowser.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using ICSharpCode.TreeView; +using ICSharpCode.Core; namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser { @@ -11,10 +11,6 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser { IAssemblyList MainAssemblyList { get; set; } ICollection AssemblyLists { get; } - - /* - IAssemblyList MainAssemblyList { get; set; } - ICollection AssemblyLists { get; } - */ + IAssemblyModel FindAssemblyModel(FileName fileName); } } diff --git a/src/Main/Base/Project/Dom/ClassBrowser/WorkspaceModel.cs b/src/Main/Base/Project/Dom/ClassBrowser/WorkspaceModel.cs index 4f72478357..2f1bc0ec4f 100644 --- a/src/Main/Base/Project/Dom/ClassBrowser/WorkspaceModel.cs +++ b/src/Main/Base/Project/Dom/ClassBrowser/WorkspaceModel.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.CompilerServices; +using ICSharpCode.Core; using ICSharpCode.TreeView; namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser @@ -41,6 +43,16 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser } } + public IAssemblyModel FindAssemblyModel(FileName fileName) + { + foreach (var list in assemblyLists) { + var model = list.Assemblies.FirstOrDefault(m => m.Location == fileName); + if (model != null) + return model; + } + return mainAssemblyList.Assemblies.FirstOrDefault(m => m.Location == fileName); + } + public WorkspaceModel() { this.assemblyLists = new SimpleModelCollection(); diff --git a/src/Main/Base/Project/Dom/ClassBrowser/WorkspaceTreeNode.cs b/src/Main/Base/Project/Dom/ClassBrowser/WorkspaceTreeNode.cs index fd6e1c29ca..0e33b3d89e 100644 --- a/src/Main/Base/Project/Dom/ClassBrowser/WorkspaceTreeNode.cs +++ b/src/Main/Base/Project/Dom/ClassBrowser/WorkspaceTreeNode.cs @@ -36,16 +36,11 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser } WorkspaceModel workspace; - protected static readonly IComparer ChildNodeComparer = new WorkspaceChildComparer(); - - public IMutableModelCollection AssemblyLists { - get { return workspace.AssemblyLists; } + public WorkspaceModel Workspace { + get { return workspace; } } - public IAssemblyList AssemblyList { - get { return workspace.MainAssemblyList; } - set { workspace.MainAssemblyList = value; } - } + protected static readonly IComparer ChildNodeComparer = new WorkspaceChildComparer(); public WorkspaceTreeNode() { @@ -68,7 +63,7 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser public override object Text { get { - return String.Format(SD.ResourceService.GetString("MainWindow.Windows.ClassBrowser.Workspace"), AssemblyList.Name); + return String.Format(SD.ResourceService.GetString("MainWindow.Windows.ClassBrowser.Workspace"), Workspace.MainAssemblyList.Name); } } diff --git a/src/Main/Base/Project/Dom/IAssemblyModel.cs b/src/Main/Base/Project/Dom/IAssemblyModel.cs index bc0558230b..0ff9db95ee 100644 --- a/src/Main/Base/Project/Dom/IAssemblyModel.cs +++ b/src/Main/Base/Project/Dom/IAssemblyModel.cs @@ -85,6 +85,11 @@ namespace ICSharpCode.SharpDevelop.Dom /// Gets the assembly name (short name). /// new string AssemblyName { get; set; } + + /// + /// Returns the assembly references. + /// + new IReadOnlyList References { get; set; } } public sealed class EmptyAssemblyModel : IAssemblyModel diff --git a/src/Main/Base/Project/Dom/ModelFactoryExtensions.cs b/src/Main/Base/Project/Dom/ModelFactoryExtensions.cs index c96ea218dc..18cb634bd2 100644 --- a/src/Main/Base/Project/Dom/ModelFactoryExtensions.cs +++ b/src/Main/Base/Project/Dom/ModelFactoryExtensions.cs @@ -4,35 +4,16 @@ using System; using System.Linq; using System.IO; +using ICSharpCode.Core; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.TypeSystem; +using Mono.Cecil; +using ICSharpCode.SharpDevelop.Parser; namespace ICSharpCode.SharpDevelop.Dom { public static class ModelFactoryExtensions { - /// - /// Creates an from a file name. - /// - /// Model factory. - /// Assembly file name. - /// Created . - public static IAssemblyModel CreateAssemblyModelFromFile(this IModelFactory modelFactory, string fileName) - { - var loader = new CecilLoader(); - loader.IncludeInternalMembers = true; - loader.LazyLoad = true; - var assembly = loader.LoadAssemblyFile(fileName); - - IEntityModelContext context = new AssemblyEntityModelContext(assembly); - IAssemblyModel model = modelFactory.CreateAssemblyModel(context); - if (model is IUpdateableAssemblyModel) { - ((IUpdateableAssemblyModel)model).Update(EmptyList.Instance, assembly.TopLevelTypeDefinitions.ToList()); - ((IUpdateableAssemblyModel) model).AssemblyName = assembly.AssemblyName; - } - return model; - } - /// /// Creates an from a file name and catches /// errors by showing messages to user. @@ -46,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Dom public static IAssemblyModel SafelyCreateAssemblyModelFromFile(this IModelFactory modelFactory, string fileName) { try { - return modelFactory.CreateAssemblyModelFromFile(fileName); + return SD.AssemblyParserService.GetAssemblyModel(new FileName(fileName), true, modelFactory); } catch (BadImageFormatException) { SD.MessageService.ShowWarningFormatted("${res:ICSharpCode.SharpDevelop.Dom.AssemblyInvalid}", Path.GetFileName(fileName)); } catch (FileNotFoundException) { diff --git a/src/Main/Base/Project/Parser/ProjectContentContainer.cs b/src/Main/Base/Project/Parser/ProjectContentContainer.cs index 8f78828b4e..7cb547128e 100644 --- a/src/Main/Base/Project/Parser/ProjectContentContainer.cs +++ b/src/Main/Base/Project/Parser/ProjectContentContainer.cs @@ -439,7 +439,7 @@ namespace ICSharpCode.SharpDevelop.Parser foreach (string file in assemblyFiles) { progressMonitor.CancellationToken.ThrowIfCancellationRequested(); if (File.Exists(file)) { - var pc = SD.AssemblyParserService.GetAssembly(FileName.Create(file), progressMonitor.CancellationToken); + var pc = SD.AssemblyParserService.GetAssembly(FileName.Create(file), false, progressMonitor.CancellationToken); if (pc != null) { newReferences.Add(pc); } diff --git a/src/Main/Base/Project/Src/Project/CompilableProject.cs b/src/Main/Base/Project/Src/Project/CompilableProject.cs index 04a768d399..e9893f8f1e 100644 --- a/src/Main/Base/Project/Src/Project/CompilableProject.cs +++ b/src/Main/Base/Project/Src/Project/CompilableProject.cs @@ -359,6 +359,8 @@ namespace ICSharpCode.SharpDevelop.Project var pc = ProjectContent; if (pc != null && assemblyModel is IUpdateableAssemblyModel) { ((IUpdateableAssemblyModel)assemblyModel).AssemblyName = AssemblyName; + ((IUpdateableAssemblyModel)assemblyModel).References = pc.AssemblyReferences + .Select(ResolveReference).Where(r => r != null).ToList(); // Add the already loaded files into the model foreach (var file in pc.Files) { ((IUpdateableAssemblyModel)assemblyModel).Update(null, file); @@ -369,6 +371,18 @@ namespace ICSharpCode.SharpDevelop.Project } } + DomAssemblyName ResolveReference(IAssemblyReference reference) + { + if (reference is IUnresolvedAssembly) + return new DomAssemblyName(((IUnresolvedAssembly)reference).FullAssemblyName); + if (reference is ProjectReferenceProjectItem) { + var project = ((ProjectReferenceProjectItem)reference).ReferencedProject; + if (project == null) return null; + return new DomAssemblyName(project.ProjectContent.FullAssemblyName); + } + return null; + } + public override void OnParseInformationUpdated(ParseInformationEventArgs args) { var c = projectContentContainer; @@ -379,6 +393,7 @@ namespace ICSharpCode.SharpDevelop.Project SD.MainThread.InvokeAsyncAndForget(delegate { if (assemblyModel is IUpdateableAssemblyModel) { ((IUpdateableAssemblyModel)assemblyModel).Update(args.OldUnresolvedFile, args.NewUnresolvedFile); + // TODO : update references as well? } ParseInformationUpdated(null, args); }); diff --git a/src/Main/SharpDevelop/Dom/AssemblyModel.cs b/src/Main/SharpDevelop/Dom/AssemblyModel.cs index 9729569a24..5474ab46a5 100644 --- a/src/Main/SharpDevelop/Dom/AssemblyModel.cs +++ b/src/Main/SharpDevelop/Dom/AssemblyModel.cs @@ -19,12 +19,14 @@ namespace ICSharpCode.SharpDevelop.Dom TopLevelTypeDefinitionModelCollection typeDeclarations; KeyedModelCollection namespaces; NamespaceModel rootNamespace; + IReadOnlyList references; public AssemblyModel(IEntityModelContext context) { if (context == null) throw new ArgumentNullException("context"); this.context = context; + this.references = EmptyList.Instance; this.rootNamespace = new NamespaceModel(context.Project, null, ""); this.typeDeclarations = new TopLevelTypeDefinitionModelCollection(context); this.typeDeclarations.CollectionChanged += TypeDeclarationsCollectionChanged; @@ -141,7 +143,8 @@ namespace ICSharpCode.SharpDevelop.Dom } public IReadOnlyList References { - get { throw new NotImplementedException(); } + get { return references; } + set { references = value; } } } } \ No newline at end of file diff --git a/src/Main/SharpDevelop/Dom/ClassBrowser/ClassBrowserPad.cs b/src/Main/SharpDevelop/Dom/ClassBrowser/ClassBrowserPad.cs index e1e38821cd..9381f37bff 100644 --- a/src/Main/SharpDevelop/Dom/ClassBrowser/ClassBrowserPad.cs +++ b/src/Main/SharpDevelop/Dom/ClassBrowser/ClassBrowserPad.cs @@ -12,6 +12,7 @@ using ICSharpCode.Core.Presentation; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.TreeView; using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Workbench; @@ -87,6 +88,11 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser set { treeView.MainAssemblyList = value; } } + public IAssemblyModel FindAssemblyModel(FileName fileName) + { + return treeView.FindAssemblyModel(fileName); + } + #endregion const string PersistedWorkspaceSetting = "ClassBrowser.Workspaces"; @@ -224,14 +230,13 @@ namespace ICSharpCode.SharpDevelop.Dom.ClassBrowser { var modelFactory = SD.GetRequiredService(); try { - return modelFactory.CreateAssemblyModelFromFile(fileName); + return SD.AssemblyParserService.GetAssemblyModel(new FileName(fileName), false, modelFactory); } catch (Exception) { // Special AssemblyModel for unresolved file references IEntityModelContext unresolvedContext = new UnresolvedAssemblyEntityModelContext(Path.GetFileName(fileName), fileName); - IAssemblyModel unresolvedModel = modelFactory.CreateAssemblyModel(unresolvedContext); - if (unresolvedModel is IUpdateableAssemblyModel) { - ((IUpdateableAssemblyModel) unresolvedModel).AssemblyName = unresolvedContext.AssemblyName; - } + IUpdateableAssemblyModel unresolvedModel = modelFactory.CreateAssemblyModel(unresolvedContext); + unresolvedModel.AssemblyName = unresolvedContext.AssemblyName; + unresolvedModel.References = EmptyList.Instance; return unresolvedModel; }