From 5d5bdc2cdb6f79daa7a51978d48a34c52b932bc1 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 5 Aug 2007 18:27:06 +0000 Subject: [PATCH] Use MSBuild's ResolveAssemblyReferences task to make sure we load the correct assembly version for code-completion. E.g. a reference to "System.Net" loads a different assembly depending on the target framework. SharpDevelop now can also find assemblies in custom reference paths, using assembly tables and everything else supported by MSBuild (including custom ResolveAssemblyReferences tasks). The property pad uses the information from MSBuild to show the resolved assembly version. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2630 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/ICSharpCode.SharpDevelop.csproj | 5 +- .../Project/Src/Project/AbstractProject.cs | 7 +- .../Base/Project/Src/Project/BuildTarget.cs | 2 + src/Main/Base/Project/Src/Project/IProject.cs | 6 + .../Src/Project/Items/ReferenceProjectItem.cs | 92 +++++++-------- .../Src/Project/MSBuildBasedProject.cs | 5 + .../Project/Src/Project/MSBuildInternals.cs | 76 ++++++++++++- .../Project/Src/Project/Solution/Solution.cs | 105 ++++++++++-------- .../LanguageBinding/LanguageBindingService.cs | 10 +- .../Net1xProjectContentRegistry.cs | 76 ------------- .../NetCFProjectContentRegistry.cs | 4 +- .../ParserService/ParseProjectContent.cs | 3 + .../Services/ParserService/ParserService.cs | 4 +- .../Project/Src/GacInterop.cs | 75 ++----------- .../Src/ProjectContent/DomAssemblyName.cs | 58 +++++++++- .../ProjectContent/ProjectContentRegistry.cs | 54 ++------- .../Src/ReflectionLayer/ReflectionLoader.cs | 4 +- 17 files changed, 290 insertions(+), 296 deletions(-) delete mode 100644 src/Main/Base/Project/Src/Services/ParserService/Net1xProjectContentRegistry.cs diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 188d30c7e4..a1af73dbcc 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -48,7 +48,9 @@ - + + True + @@ -681,7 +683,6 @@ - SolutionConfigurationEditor.cs diff --git a/src/Main/Base/Project/Src/Project/AbstractProject.cs b/src/Main/Base/Project/Src/Project/AbstractProject.cs index a16f214019..2265903142 100644 --- a/src/Main/Base/Project/Src/Project/AbstractProject.cs +++ b/src/Main/Base/Project/Src/Project/AbstractProject.cs @@ -445,11 +445,12 @@ namespace ICSharpCode.SharpDevelop.Project return ItemType.None; } - /// - /// Gets the minimum version the solution must have to support this project type. - /// public virtual int MinimumSolutionVersion { get { return 9; } } + + public virtual void ResolveAssemblyReferences() + { + } } } diff --git a/src/Main/Base/Project/Src/Project/BuildTarget.cs b/src/Main/Base/Project/Src/Project/BuildTarget.cs index 5b829068a6..9e9e931ad2 100644 --- a/src/Main/Base/Project/Src/Project/BuildTarget.cs +++ b/src/Main/Base/Project/Src/Project/BuildTarget.cs @@ -20,6 +20,8 @@ namespace ICSharpCode.SharpDevelop.Project public readonly static BuildTarget Build = new BuildTarget("Build"); public readonly static BuildTarget Rebuild = new BuildTarget("Rebuild"); public readonly static BuildTarget Clean = new BuildTarget("Clean"); + + public readonly static BuildTarget ResolveReferences = new BuildTarget("ResolveReferences"); public readonly static BuildTarget ResolveComReferences = new BuildTarget("ResolveComReferences"); readonly string targetName; diff --git a/src/Main/Base/Project/Src/Project/IProject.cs b/src/Main/Base/Project/Src/Project/IProject.cs index 343fd90a78..1bb117b34d 100644 --- a/src/Main/Base/Project/Src/Project/IProject.cs +++ b/src/Main/Base/Project/Src/Project/IProject.cs @@ -216,6 +216,12 @@ namespace ICSharpCode.SharpDevelop.Project /// Gets the minimum version the solution must have to support this project type. /// int MinimumSolutionVersion { get; } + + /// + /// Retrieve the fully qualified assembly names and file location of referenced assemblies. + /// This method is thread safe. + /// + void ResolveAssemblyReferences(); } /// diff --git a/src/Main/Base/Project/Src/Project/Items/ReferenceProjectItem.cs b/src/Main/Base/Project/Src/Project/Items/ReferenceProjectItem.cs index 43b19b83f9..f896a6f849 100644 --- a/src/Main/Base/Project/Src/Project/Items/ReferenceProjectItem.cs +++ b/src/Main/Base/Project/Src/Project/Items/ReferenceProjectItem.cs @@ -12,6 +12,7 @@ using System.Reflection; using System.Text; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Gui; namespace ICSharpCode.SharpDevelop.Project @@ -72,27 +73,36 @@ namespace ICSharpCode.SharpDevelop.Project } } + internal const string CopyLocalMetadataName = "Private"; + [LocalizedProperty("${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.LocalCopy}", Description = "${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.LocalCopy.Description}")] - public bool Private { + public bool CopyLocal { get { - return GetEvaluatedMetadata("Private", !IsGacReference); + return GetEvaluatedMetadata(CopyLocalMetadataName, !IsGacReference); } set { - SetEvaluatedMetadata("Private", value); + SetEvaluatedMetadata(CopyLocalMetadataName, value); } } + DomAssemblyName assemblyName; + + /// + /// Gets the assembly name. + /// + [Browsable(false)] + public DomAssemblyName AssemblyName { + get { return assemblyName ?? new DomAssemblyName(Include); } + internal set { assemblyName = value; } + } + [ReadOnly(true)] [LocalizedProperty("${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Name}", Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Name.Description}")] public string Name { get { - AssemblyName assemblyName = GetAssemblyName(Include); - if (assemblyName != null) { - return assemblyName.Name; - } - return Include; + return this.AssemblyName.ShortName; } } @@ -101,11 +111,10 @@ namespace ICSharpCode.SharpDevelop.Project Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Version.Description}")] public Version Version { get { - AssemblyName assemblyName = GetAssemblyName(Include); - if (assemblyName != null) { - return assemblyName.Version; - } - return null; + if (this.AssemblyName.Version == null) + return null; + else + return new Version(this.AssemblyName.Version); } } @@ -114,11 +123,7 @@ namespace ICSharpCode.SharpDevelop.Project Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Culture.Description}")] public string Culture { get { - AssemblyName assemblyName = GetAssemblyName(Include); - if (assemblyName != null && assemblyName.CultureInfo != null) { - return assemblyName.CultureInfo.Name; - } - return null; + return this.AssemblyName.Culture; } } @@ -127,24 +132,32 @@ namespace ICSharpCode.SharpDevelop.Project Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.PublicKeyToken.Description}")] public string PublicKeyToken { get { - AssemblyName assemblyName = GetAssemblyName(Include); - if (assemblyName != null) { - byte[] bytes = assemblyName.GetPublicKeyToken(); - if (bytes != null) { - StringBuilder token = new StringBuilder(); - foreach (byte b in bytes) { - token.Append(b.ToString("x2")); - } - return token.ToString(); - } - } - return null; + return this.AssemblyName.PublicKeyToken; } } + string redist; + + /// + /// The name of the package in which the assembly is redistributed to the user. + /// "Microsoft-Windows-CLRCoreComp" = .NET 2.0 + /// "Microsoft-Windows-CLRCoreComp-v3.5" = .NET 3.5 + /// + [Browsable(false)] + public string Redist { + get { return redist; } + set { redist = value; } + } + + string fullPath; + [ReadOnly(true)] public override string FileName { get { + if (fullPath != null) { + return fullPath; + } + if (Project != null) { string projectDir = Project.Directory; string hintPath = HintPath; @@ -167,7 +180,7 @@ namespace ICSharpCode.SharpDevelop.Project return Include; } set { - // Set by file name is unsupported by references. (otherwise GAC references might have strange renaming effects ...) + fullPath = value; } } @@ -178,23 +191,12 @@ namespace ICSharpCode.SharpDevelop.Project } } - AssemblyName GetAssemblyName(string include) - { - try { - if (this.ItemType == ItemType.Reference) { - return new AssemblyName(include); - } - } catch (ArgumentException) { } - - return null; - } - protected override void FilterProperties(PropertyDescriptorCollection globalizedProps) { base.FilterProperties(globalizedProps); - PropertyDescriptor privatePD = globalizedProps["Private"]; - globalizedProps.Remove(privatePD); - globalizedProps.Add(new ReplaceDefaultValueDescriptor(privatePD, !IsGacReference)); + PropertyDescriptor copyLocalPD = globalizedProps["CopyLocal"]; + globalizedProps.Remove(copyLocalPD); + globalizedProps.Add(new ReplaceDefaultValueDescriptor(copyLocalPD, !IsGacReference)); } sealed class ReplaceDefaultValueDescriptor : PropertyDescriptor diff --git a/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs b/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs index 8b953f2ecd..dd5f40896d 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs @@ -74,6 +74,11 @@ namespace ICSharpCode.SharpDevelop.Project } } + public override void ResolveAssemblyReferences() + { + MSBuildInternals.ResolveAssemblyReferences(this, null); + } + #region CreateProjectItem /// /// Creates a new projectItem for the passed itemType diff --git a/src/Main/Base/Project/Src/Project/MSBuildInternals.cs b/src/Main/Base/Project/Src/Project/MSBuildInternals.cs index 9861b49cb1..a64c00ca15 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildInternals.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildInternals.cs @@ -5,16 +5,18 @@ // $Revision$ // +using ICSharpCode.Core; using System; -using System.Diagnostics; +using System.IO; using System.Collections; using System.Collections.Generic; -using System.Linq; -using System.Xml; -using System.Text; +using System.Diagnostics; using System.Globalization; +using System.Linq; using System.Reflection; +using System.Text; using System.Text.RegularExpressions; +using System.Xml; using MSBuild = Microsoft.Build.BuildEngine; namespace ICSharpCode.SharpDevelop.Project @@ -229,6 +231,9 @@ namespace ICSharpCode.SharpDevelop.Project /// public static void ClearImports(MSBuild.Project project) { + if (project == null) + throw new ArgumentNullException("project"); + XmlElement xmlProject = BeginXmlManipulation(project); List nodesToRemove = new List(); foreach (XmlNode node in xmlProject.ChildNodes) { @@ -239,6 +244,7 @@ namespace ICSharpCode.SharpDevelop.Project foreach (XmlNode node in nodesToRemove) { xmlProject.RemoveChild(node); } + EndXmlManipulation(project); } /// @@ -303,5 +309,67 @@ namespace ICSharpCode.SharpDevelop.Project null, project, null ); } + + internal static void ResolveAssemblyReferences(MSBuildBasedProject baseProject, ReferenceProjectItem[] referenceReplacements) + { + MSBuild.Engine engine; + MSBuild.Project tempProject; + IEnumerable references; + + lock (baseProject.SyncRoot) { + // create a copy of the project + engine = CreateEngine(); + tempProject = engine.CreateNewProject(); + // tell MSBuild the path so that projects containing + // can be loaded + tempProject.FullFileName = baseProject.MSBuildProject.FullFileName; + MSBuildBasedProject.InitializeMSBuildProject(tempProject); + tempProject.LoadXml(baseProject.MSBuildProject.Xml); + tempProject.SetProperty("Configuration", baseProject.ActiveConfiguration); + tempProject.SetProperty("Platform", baseProject.ActivePlatform); + tempProject.SetProperty("BuildingProject", "false"); + + if (referenceReplacements == null) { + references = baseProject.GetItemsOfType(ItemType.Reference).OfType(); + } else { + references = referenceReplacements; + + foreach (MSBuild.BuildItemGroup itemGroup in tempProject.ItemGroups) { + foreach (MSBuild.BuildItem item in itemGroup.ToArray()) { + if (item.Name == ItemType.Reference.ItemName) { + itemGroup.RemoveItem(item); + } + } + } + foreach (ReferenceProjectItem item in referenceReplacements) { + tempProject.AddNewItem("Reference", item.Include, true); + } + } + } + var referenceDict = references.ToDictionary(item => item.Include); + + engine.RegisterLogger(new MSBuild.ConsoleLogger(Microsoft.Build.Framework.LoggerVerbosity.Detailed)); + + //Environment.CurrentDirectory = Path.GetDirectoryName(tempProject.FullFileName); + if (!tempProject.Build("ResolveAssemblyReferences")) { + LoggingService.Warn("ResolveAssemblyReferences exited with error"); + return; + } + + foreach (MSBuild.BuildItem item in tempProject.GetEvaluatedItemsByName("_ResolveAssemblyReferenceResolvedFiles")) { + string originalInclude = item.GetEvaluatedMetadata("OriginalItemSpec"); + ReferenceProjectItem reference; + if (referenceDict.TryGetValue(originalInclude, out reference)) { + reference.AssemblyName = new Dom.DomAssemblyName(item.GetEvaluatedMetadata("FusionName")); + //string fullPath = item.GetEvaluatedMetadata("FullPath"); is incorrect for relative paths + string fullPath = FileUtility.GetAbsolutePath(baseProject.Directory, item.GetEvaluatedMetadata("Identity")); + reference.FileName = fullPath; + reference.Redist = item.GetEvaluatedMetadata("Redist"); + LoggingService.Debug("Got information about " + originalInclude + "; fullpath=" + fullPath); + } else { + LoggingService.Warn("Unknown item " + originalInclude); + } + } + } } } diff --git a/src/Main/Base/Project/Src/Project/Solution/Solution.cs b/src/Main/Base/Project/Src/Project/Solution/Solution.cs index 9b963628ca..07714f31ca 100644 --- a/src/Main/Base/Project/Src/Project/Solution/Solution.cs +++ b/src/Main/Base/Project/Src/Project/Solution/Solution.cs @@ -12,8 +12,9 @@ using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; - +using SearchAndReplace; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; using MSBuild = Microsoft.Build.BuildEngine; namespace ICSharpCode.SharpDevelop.Project @@ -445,19 +446,18 @@ namespace ICSharpCode.SharpDevelop.Project } } - static bool SetupSolution(Solution newSolution, string fileName) + static bool SetupSolution(Solution newSolution) { - string solutionDirectory = Path.GetDirectoryName(fileName); ProjectSection nestedProjectsSection = null; bool needsConversion = false; // read solution files using system encoding, but detect UTF8 if BOM is present - using (StreamReader sr = new StreamReader(fileName, Encoding.Default, true)) { + using (StreamReader sr = new StreamReader(newSolution.FileName, Encoding.Default, true)) { string line = GetFirstNonCommentLine(sr); Match match = versionPattern.Match(line); if (!match.Success) { - MessageService.ShowErrorFormatted("${res:SharpDevelop.Solution.InvalidSolutionFile}", fileName); + MessageService.ShowErrorFormatted("${res:SharpDevelop.Solution.InvalidSolutionFile}", newSolution.FileName); return false; } @@ -482,47 +482,8 @@ namespace ICSharpCode.SharpDevelop.Project return false; } - while (true) { - line = sr.ReadLine(); - - if (line == null) { - break; - } - match = projectLinePattern.Match(line); - if (match.Success) { - string projectGuid = match.Result("${ProjectGuid}"); - string title = match.Result("${Title}"); - string location = match.Result("${Location}"); - string guid = match.Result("${Guid}"); - - if (!FileUtility.IsUrl(location)) { - location = FileUtility.NormalizePath(Path.Combine(solutionDirectory, location)); - } - - if (projectGuid == FolderGuid) { - SolutionFolder newFolder = SolutionFolder.ReadFolder(sr, title, location, guid); - newSolution.AddFolder(newFolder); - } else { - IProject newProject = LanguageBindingService.LoadProject(newSolution, location, title, projectGuid); - ReadProjectSections(sr, newProject.ProjectSections); - newProject.IdGuid = guid; - newSolution.AddFolder(newProject); - } - match = match.NextMatch(); - } else { - match = globalSectionPattern.Match(line); - if (match.Success) { - ProjectSection newSection = ProjectSection.ReadGlobalSection(sr, match.Result("${Name}"), match.Result("${Type}")); - // Don't put the NestedProjects section into the global sections list - // because it's transformed to a tree representation and the tree representation - // is transformed back to the NestedProjects section during save. - if (newSection.Name == "NestedProjects") { - nestedProjectsSection = newSection; - } else { - newSolution.Sections.Add(newSection); - } - } - } + using (AsynchronousWaitDialog waitDialog = AsynchronousWaitDialog.ShowWaitDialog("Loading solution")) { + nestedProjectsSection = SetupSolutionLoadSolutionProjects(newSolution, sr, waitDialog); } } // Create solution folder 'tree'. @@ -545,6 +506,56 @@ namespace ICSharpCode.SharpDevelop.Project } return true; } + + static ProjectSection SetupSolutionLoadSolutionProjects(Solution newSolution, StreamReader sr, IProgressMonitor progressMonitor) + { + string solutionDirectory = Path.GetDirectoryName(newSolution.FileName); + + ProjectSection nestedProjectsSection = null; + while (true) { + string line = sr.ReadLine(); + + if (line == null) { + break; + } + Match match = projectLinePattern.Match(line); + if (match.Success) { + string projectGuid = match.Result("${ProjectGuid}"); + string title = match.Result("${Title}"); + string location = match.Result("${Location}"); + string guid = match.Result("${Guid}"); + + if (!FileUtility.IsUrl(location)) { + location = FileUtility.NormalizePath(Path.Combine(solutionDirectory, location)); + } + + if (projectGuid == FolderGuid) { + SolutionFolder newFolder = SolutionFolder.ReadFolder(sr, title, location, guid); + newSolution.AddFolder(newFolder); + } else { + IProject newProject = LanguageBindingService.LoadProject(newSolution, location, title, projectGuid, progressMonitor); + ReadProjectSections(sr, newProject.ProjectSections); + newProject.IdGuid = guid; + newSolution.AddFolder(newProject); + } + match = match.NextMatch(); + } else { + match = globalSectionPattern.Match(line); + if (match.Success) { + ProjectSection newSection = ProjectSection.ReadGlobalSection(sr, match.Result("${Name}"), match.Result("${Type}")); + // Don't put the NestedProjects section into the global sections list + // because it's transformed to a tree representation and the tree representation + // is transformed back to the NestedProjects section during save. + if (newSection.Name == "NestedProjects") { + nestedProjectsSection = newSection; + } else { + newSolution.Sections.Add(newSection); + } + } + } + } + return nestedProjectsSection; + } #endregion #region Configuration/Platform management @@ -1108,7 +1119,7 @@ namespace ICSharpCode.SharpDevelop.Project } } else { newSolution.fileName = fileName; - if (!SetupSolution(newSolution, fileName)) { + if (!SetupSolution(newSolution)) { return null; } } diff --git a/src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingService.cs b/src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingService.cs index 93c96b5366..5e699bd079 100644 --- a/src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingService.cs +++ b/src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingService.cs @@ -5,11 +5,11 @@ // $Revision$ // +using ICSharpCode.SharpDevelop.Gui; using System; using System.Collections.Generic; using System.IO; using System.Xml; - using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Project; @@ -90,10 +90,10 @@ namespace ICSharpCode.SharpDevelop public static IProject LoadProject(IMSBuildEngineProvider provider, string location, string title) { - return LoadProject(provider, location, title, "{" + Guid.Empty.ToString() + "}"); + return LoadProject(provider, location, title, "{" + Guid.Empty.ToString() + "}", null); } - public static IProject LoadProject(IMSBuildEngineProvider provider, string location, string title, string projectTypeGuid) + public static IProject LoadProject(IMSBuildEngineProvider provider, string location, string title, string projectTypeGuid, IProgressMonitor progressMonitor) { if (provider == null) throw new ArgumentNullException("provider"); @@ -104,6 +104,10 @@ namespace ICSharpCode.SharpDevelop if (projectTypeGuid == null) throw new ArgumentNullException("projectTypeGuid"); + if (progressMonitor != null) { + progressMonitor.BeginTask("Loading " + title, 0, false); + } + IProject newProject; if (!File.Exists(location)) { newProject = new MissingProject(location, title); diff --git a/src/Main/Base/Project/Src/Services/ParserService/Net1xProjectContentRegistry.cs b/src/Main/Base/Project/Src/Services/ParserService/Net1xProjectContentRegistry.cs deleted file mode 100644 index a9fa9a3e82..0000000000 --- a/src/Main/Base/Project/Src/Services/ParserService/Net1xProjectContentRegistry.cs +++ /dev/null @@ -1,76 +0,0 @@ -// -// -// -// -// $Revision$ -// - -using System; -using System.IO; -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Dom; - -namespace ICSharpCode.SharpDevelop -{ - /// - /// Project content registry for .NET 1.0 and .NET 1.1 assemblies. - /// - public abstract class Net1xProjectContentRegistry : ProjectContentRegistry - { - protected abstract string DotnetVersion { get; } - - public override IProjectContent Mscorlib { - get { - return GetProjectContentForReference("mscorlib", "mscorlib"); - } - } - - protected override IProjectContent LoadProjectContent(string itemInclude, string itemFileName) - { - if (File.Exists(itemFileName)) { - return base.LoadProjectContent(itemInclude, itemFileName); - } - string netPath = Path.Combine(FileUtility.NETFrameworkInstallRoot, DotnetVersion); - if (File.Exists(Path.Combine(netPath, "mscorlib.dll"))) { - string shortName = itemInclude; - int pos = shortName.IndexOf(','); - if (pos > 0) - shortName = shortName.Substring(0, pos); - - if (File.Exists(Path.Combine(netPath, shortName + ".dll"))) { - ReflectionProjectContent rpc = CecilReader.LoadAssembly(Path.Combine(netPath, shortName + ".dll"), this); - if (rpc != null) { - redirectedAssemblyNames.Add(shortName, rpc.AssemblyFullName); - } - return rpc; - } else if (File.Exists(Path.Combine(netPath, shortName))) { - // perhaps shortName includes file extension - ReflectionProjectContent rpc = CecilReader.LoadAssembly(Path.Combine(netPath, shortName), this); - if (rpc != null) { - redirectedAssemblyNames.Add(Path.GetFileNameWithoutExtension(shortName), rpc.AssemblyFullName); - } - return rpc; - } - } else { - string message = "Warning: Target .NET Framework version " + DotnetVersion + " is not installed." + Environment.NewLine; - if (!TaskService.BuildMessageViewCategory.Text.Contains(message)) { - TaskService.BuildMessageViewCategory.AppendText(message); - } - } - return base.LoadProjectContent(itemInclude, itemFileName); - } - } - - public class Net10ProjectContentRegistry : Net1xProjectContentRegistry - { - protected override string DotnetVersion { - get { return "v1.0.3705"; } - } - } - public class Net11ProjectContentRegistry : Net1xProjectContentRegistry - { - protected override string DotnetVersion { - get { return "v1.1.4322"; } - } - } -} diff --git a/src/Main/Base/Project/Src/Services/ParserService/NetCFProjectContentRegistry.cs b/src/Main/Base/Project/Src/Services/ParserService/NetCFProjectContentRegistry.cs index 88edc813db..b4a1a8dfcc 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/NetCFProjectContentRegistry.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/NetCFProjectContentRegistry.cs @@ -32,7 +32,8 @@ namespace ICSharpCode.SharpDevelop return null; } - + /* + Is this still required now that we use MSBuild to resolve assembly references? protected override IProjectContent LoadProjectContent(string itemInclude, string itemFileName) { if (File.Exists(itemFileName)) { @@ -70,5 +71,6 @@ namespace ICSharpCode.SharpDevelop } return base.LoadProjectContent(itemInclude, itemFileName); } + */ } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs index e26aec6b08..70b93220f8 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs @@ -47,6 +47,9 @@ namespace ICSharpCode.SharpDevelop ProjectService.ProjectItemAdded += OnProjectItemAdded; ProjectService.ProjectItemRemoved += OnProjectItemRemoved; UpdateDefaultImports(items); + StatusBarService.ProgressMonitor.BeginTask("Resolving references for " + project.Name, 0, false); + project.ResolveAssemblyReferences(); + StatusBarService.ProgressMonitor.Done(); foreach (ProjectItem item in items) { if (!initializing) return; // abort initialization if (item.ItemType == ItemType.Reference diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 531561bf6d..c84cea8d05 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -126,6 +126,7 @@ namespace ICSharpCode.SharpDevelop } } loadSolutionProjectsThread = new Thread(new ThreadStart(LoadSolutionProjects)); + loadSolutionProjectsThread.SetApartmentState(ApartmentState.STA); // allow loadSolutionProjects thread access to MSBuild loadSolutionProjectsThread.Name = "loadSolutionProjects"; loadSolutionProjectsThread.Priority = ThreadPriority.BelowNormal; loadSolutionProjectsThread.IsBackground = true; @@ -280,6 +281,7 @@ namespace ICSharpCode.SharpDevelop if (reParseThread == null) { LoggingService.Info("Starting reParse thread"); reParseThread = new Thread(new ThreadStart(ReparseProjects)); + reParseThread.SetApartmentState(ApartmentState.STA); // allow reParseThread access to MSBuild reParseThread.Name = "reParse"; reParseThread.Priority = ThreadPriority.BelowNormal; reParseThread.IsBackground = true; @@ -764,7 +766,7 @@ namespace ICSharpCode.SharpDevelop } return ParserService.GetProjectContent(((ProjectReferenceProjectItem)item).ReferencedProject); } - return GetRegistryForReference(item).GetExistingProjectContent(item.Include, item.FileName); + return GetRegistryForReference(item).GetExistingProjectContent(item.FileName); } public static IProjectContent GetProjectContentForReference(ReferenceProjectItem item) diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs index 9f271f8548..449c09ff33 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs @@ -69,21 +69,21 @@ namespace ICSharpCode.SharpDevelop.Dom /// /// Gets the full display name of the GAC assembly of the specified short name /// - public static GacAssemblyName FindBestMatchingAssemblyName(string name) + public static DomAssemblyName FindBestMatchingAssemblyName(string name) { - return FindBestMatchingAssemblyName(new GacAssemblyName(name)); + return FindBestMatchingAssemblyName(new DomAssemblyName(name)); } - public static GacAssemblyName FindBestMatchingAssemblyName(GacAssemblyName name) + public static DomAssemblyName FindBestMatchingAssemblyName(DomAssemblyName name) { string[] info; string version = name.Version; - string publicKey = name.PublicKey; + string publicKey = name.PublicKeyToken; IApplicationContext applicationContext = null; IAssemblyEnum assemblyEnum = null; IAssemblyName assemblyName; - Fusion.CreateAssemblyNameObject(out assemblyName, name.Name, 0, 0); + Fusion.CreateAssemblyNameObject(out assemblyName, name.ShortName, 0, 0); Fusion.CreateAssemblyEnum(out assemblyEnum, null, assemblyName, 2, 0); List names = new List(); @@ -123,7 +123,7 @@ namespace ICSharpCode.SharpDevelop.Dom } } if (best != null) - return new GacAssemblyName(best); + return new DomAssemblyName(best); } // use assembly with highest version best = names[0]; @@ -137,68 +137,7 @@ namespace ICSharpCode.SharpDevelop.Dom best = names[i]; } } - return new GacAssemblyName(best); - } - } - - public class GacAssemblyName : IEquatable - { - readonly string fullName; - readonly string[] info; - - public GacAssemblyName(string fullName) - { - if (fullName == null) - throw new ArgumentNullException("fullName"); - this.fullName = fullName; - info = fullName.Split(','); - } - - public string Name { - get { - return info[0]; - } - } - - public string Version { - get { - return (info.Length > 1) ? info[1].Substring(info[1].LastIndexOf('=') + 1) : null; - } - } - - public string PublicKey { - get { - return (info.Length > 3) ? info[3].Substring(info[3].LastIndexOf('=') + 1) : null; - } - } - - public string FullName { - get { return fullName; } - } - - - - public override string ToString() - { - return fullName; - } - - public bool Equals(GacAssemblyName other) - { - if (other == null) - return false; - else - return fullName == other.fullName; - } - - public override bool Equals(object obj) - { - return Equals(obj as GacAssemblyName); - } - - public override int GetHashCode() - { - return fullName.GetHashCode(); + return new DomAssemblyName(best); } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DomAssemblyName.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DomAssemblyName.cs index d1ddb78dea..6e7a3c96d8 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DomAssemblyName.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DomAssemblyName.cs @@ -13,19 +13,75 @@ namespace ICSharpCode.SharpDevelop.Dom /// Similar to System.Reflection.AssemblyName, but does not raise an exception /// on invalid assembly names. (See SD2-1307) /// - public sealed class DomAssemblyName + public sealed class DomAssemblyName : IEquatable { readonly string fullAssemblyName; + readonly string shortName, version, culture, publicKeyToken; public DomAssemblyName(string fullAssemblyName) { this.fullAssemblyName = fullAssemblyName; + string[] components = fullAssemblyName.Split(','); + shortName = components[0]; + for (int i = 1; i < components.Length; i++) { + string val = components[i].Trim(); + int pos = val.IndexOf('='); + if (pos > 0) { + switch (val.Substring(0, pos)) { + case "Version": + version = val.Substring(pos + 1); + break; + case "Culture": + culture = val.Substring(pos + 1); + break; + case "PublicKeyToken": + publicKeyToken = val.Substring(pos + 1); + break; + } + } + } } public string FullName { get { return fullAssemblyName; } } + public string ShortName { + get { return shortName; } + } + + public string Version { + get { return version; } + } + + public string Culture { + get { return culture; } + } + + public string PublicKeyToken { + get { return publicKeyToken; } + } + + public override string ToString() + { + return fullAssemblyName; + } + + public override int GetHashCode() + { + return fullAssemblyName.GetHashCode(); + } + + public override bool Equals(object obj) + { + return Equals(obj as DomAssemblyName); + } + + public bool Equals(DomAssemblyName other) + { + return other != null && fullAssemblyName == other.fullAssemblyName; + } + internal static DomAssemblyName[] Convert(System.Reflection.AssemblyName[] names) { if (names == null) return null; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ProjectContentRegistry.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ProjectContentRegistry.cs index bb3b74d3ea..797f682cc6 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ProjectContentRegistry.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ProjectContentRegistry.cs @@ -24,11 +24,6 @@ namespace ICSharpCode.SharpDevelop.Dom internal DomPersistence persistence; Dictionary contents = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - /// - /// Redirects short names to long names. Used to redirect .NET libraries to the chosen .NET version - /// - protected Dictionary redirectedAssemblyNames = new Dictionary(); - /// /// Disposes all project contents stored in this registry. /// @@ -177,9 +172,6 @@ namespace ICSharpCode.SharpDevelop.Dom contents["mscorlib"] = mscorlibContent; contents[mscorlibContent.AssemblyFullName] = mscorlibContent; contents[mscorlibContent.AssemblyLocation] = mscorlibContent; - lock (redirectedAssemblyNames) { - redirectedAssemblyNames.Add("mscorlib", mscorlibContent.AssemblyFullName); - } return mscorlibContent; } } @@ -218,31 +210,14 @@ namespace ICSharpCode.SharpDevelop.Dom public IProjectContent GetExistingProjectContent(DomAssemblyName assembly) { - return GetExistingProjectContent(assembly.FullName, assembly.FullName); + return GetExistingProjectContent(assembly.FullName); } - public virtual IProjectContent GetExistingProjectContent(string itemInclude, string itemFileName) + public virtual IProjectContent GetExistingProjectContent(string fileNameOrAssemblyName) { - if (itemFileName == itemInclude) { - string shortName = itemInclude; - int pos = shortName.IndexOf(','); - if (pos > 0) - shortName = shortName.Substring(0, pos); - - // redirect all references to .NET default assemblies to the .NET version this registry uses - lock (redirectedAssemblyNames) { - if (redirectedAssemblyNames.ContainsKey(shortName)) { - itemFileName = redirectedAssemblyNames[shortName]; - itemInclude = shortName; - } - } - } lock (contents) { - if (contents.ContainsKey(itemFileName)) { - return contents[itemFileName]; - } - if (contents.ContainsKey(itemInclude)) { - return contents[itemInclude]; + if (contents.ContainsKey(fileNameOrAssemblyName)) { + return contents[fileNameOrAssemblyName]; } } return null; @@ -251,7 +226,7 @@ namespace ICSharpCode.SharpDevelop.Dom public virtual IProjectContent GetProjectContentForReference(string itemInclude, string itemFileName) { lock (contents) { - IProjectContent pc = GetExistingProjectContent(itemInclude, itemFileName); + IProjectContent pc = GetExistingProjectContent(itemFileName); if (pc != null) { return pc; } @@ -310,26 +285,19 @@ namespace ICSharpCode.SharpDevelop.Dom persistence.SaveProjectContent(pc); } } - if (pc != null) { - // add default .NET assemblies to redirected assemblies (both when loaded from persistence - // and when loaded using Reflection) - lock (redirectedAssemblyNames) { - redirectedAssemblyNames[shortName] = pc.AssemblyFullName; - } - } } else { // find real file name for cecil: if (File.Exists(itemFileName)) { pc = CecilReader.LoadAssembly(itemFileName, this); } else { - GacAssemblyName asmName = GacInterop.FindBestMatchingAssemblyName(itemInclude); + DomAssemblyName asmName = GacInterop.FindBestMatchingAssemblyName(itemInclude); if (persistence != null && asmName != null) { //LoggingService.Debug("Looking up in DOM cache: " + asmName.FullName); pc = persistence.LoadProjectContentByAssemblyName(asmName.FullName); } if (pc == null && asmName != null) { - string subPath = Path.Combine(asmName.Name, GetVersion__Token(asmName)); - subPath = Path.Combine(subPath, asmName.Name + ".dll"); + string subPath = Path.Combine(asmName.ShortName, GetVersion__Token(asmName)); + subPath = Path.Combine(subPath, asmName.ShortName + ".dll"); foreach (string dir in Directory.GetDirectories(GacInterop.GacRootPath, "GAC*")) { itemFileName = Path.Combine(dir, subPath); if (File.Exists(itemFileName)) { @@ -342,18 +310,18 @@ namespace ICSharpCode.SharpDevelop.Dom } } if (pc == null) { - HostCallback.ShowAssemblyLoadErrorInternal("?", itemInclude, "Could not find assembly file."); + HostCallback.ShowAssemblyLoadErrorInternal(itemFileName, itemInclude, "Could not find assembly file."); } } } return pc; } - static string GetVersion__Token(GacAssemblyName asmName) + static string GetVersion__Token(DomAssemblyName asmName) { StringBuilder b = new StringBuilder(asmName.Version.ToString()); b.Append("__"); - b.Append(asmName.PublicKey); + b.Append(asmName.PublicKeyToken); return b.ToString(); } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionLoader.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionLoader.cs index 932b654e78..b74d329181 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionLoader.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionLoader.cs @@ -21,7 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom public static Assembly ReflectionLoadGacAssembly(string partialName, bool reflectionOnly) { if (reflectionOnly) { - GacAssemblyName name = GacInterop.FindBestMatchingAssemblyName(partialName); + DomAssemblyName name = GacInterop.FindBestMatchingAssemblyName(partialName); if (name == null) return null; return Assembly.ReflectionOnlyLoad(name.FullName); @@ -98,7 +98,7 @@ namespace ICSharpCode.SharpDevelop.Dom LoggingService.Warn("AssemblyResolve: ReflectionOnlyLoad failed for " + e.Name); // We can't get the assembly we want. // But propably we can get a similar version of it. - GacAssemblyName fixedName = GacInterop.FindBestMatchingAssemblyName(e.Name); + DomAssemblyName fixedName = GacInterop.FindBestMatchingAssemblyName(e.Name); LoggingService.Info("AssemblyResolve: FixedName: " + fixedName); return Assembly.ReflectionOnlyLoad(fixedName.FullName); }