Browse Source

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
shortcuts
Daniel Grunwald 19 years ago
parent
commit
5d5bdc2cdb
  1. 5
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 7
      src/Main/Base/Project/Src/Project/AbstractProject.cs
  3. 2
      src/Main/Base/Project/Src/Project/BuildTarget.cs
  4. 6
      src/Main/Base/Project/Src/Project/IProject.cs
  5. 88
      src/Main/Base/Project/Src/Project/Items/ReferenceProjectItem.cs
  6. 5
      src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs
  7. 76
      src/Main/Base/Project/Src/Project/MSBuildInternals.cs
  8. 69
      src/Main/Base/Project/Src/Project/Solution/Solution.cs
  9. 10
      src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingService.cs
  10. 76
      src/Main/Base/Project/Src/Services/ParserService/Net1xProjectContentRegistry.cs
  11. 4
      src/Main/Base/Project/Src/Services/ParserService/NetCFProjectContentRegistry.cs
  12. 3
      src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
  13. 4
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  14. 75
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs
  15. 58
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DomAssemblyName.cs
  16. 54
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ProjectContentRegistry.cs
  17. 4
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionLoader.cs

5
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -48,7 +48,9 @@
<Reference Include="System.Web.Services" /> <Reference Include="System.Web.Services" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" /> <Reference Include="System.XML" />
<Reference Include="Microsoft.Build.Framework" /> <Reference Include="Microsoft.Build.Framework">
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Build.Engine" /> <Reference Include="Microsoft.Build.Engine" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -681,7 +683,6 @@
<Compile Include="Src\Services\ParserService\Doozer\ProjectContentRegistryDescriptor.cs" /> <Compile Include="Src\Services\ParserService\Doozer\ProjectContentRegistryDescriptor.cs" />
<Compile Include="Src\Services\ParserService\Doozer\ProjectContentRegistryDoozer.cs" /> <Compile Include="Src\Services\ParserService\Doozer\ProjectContentRegistryDoozer.cs" />
<Compile Include="Src\Internal\ConditionEvaluators\CompareProjectPropertyConditionEvaluator.cs" /> <Compile Include="Src\Internal\ConditionEvaluators\CompareProjectPropertyConditionEvaluator.cs" />
<Compile Include="Src\Services\ParserService\Net1xProjectContentRegistry.cs" />
<Compile Include="Src\Services\ParserService\NetCFProjectContentRegistry.cs" /> <Compile Include="Src\Services\ParserService\NetCFProjectContentRegistry.cs" />
<Compile Include="Src\Gui\Dialogs\SolutionConfiguration\SolutionConfigurationEditor.Designer.cs"> <Compile Include="Src\Gui\Dialogs\SolutionConfiguration\SolutionConfigurationEditor.Designer.cs">
<DependentUpon>SolutionConfigurationEditor.cs</DependentUpon> <DependentUpon>SolutionConfigurationEditor.cs</DependentUpon>

7
src/Main/Base/Project/Src/Project/AbstractProject.cs

@ -445,11 +445,12 @@ namespace ICSharpCode.SharpDevelop.Project
return ItemType.None; return ItemType.None;
} }
/// <summary>
/// Gets the minimum version the solution must have to support this project type.
/// </summary>
public virtual int MinimumSolutionVersion { public virtual int MinimumSolutionVersion {
get { return 9; } get { return 9; }
} }
public virtual void ResolveAssemblyReferences()
{
}
} }
} }

2
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 Build = new BuildTarget("Build");
public readonly static BuildTarget Rebuild = new BuildTarget("Rebuild"); public readonly static BuildTarget Rebuild = new BuildTarget("Rebuild");
public readonly static BuildTarget Clean = new BuildTarget("Clean"); public readonly static BuildTarget Clean = new BuildTarget("Clean");
public readonly static BuildTarget ResolveReferences = new BuildTarget("ResolveReferences");
public readonly static BuildTarget ResolveComReferences = new BuildTarget("ResolveComReferences"); public readonly static BuildTarget ResolveComReferences = new BuildTarget("ResolveComReferences");
readonly string targetName; readonly string targetName;

6
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. /// Gets the minimum version the solution must have to support this project type.
/// </summary> /// </summary>
int MinimumSolutionVersion { get; } int MinimumSolutionVersion { get; }
/// <summary>
/// Retrieve the fully qualified assembly names and file location of referenced assemblies.
/// This method is thread safe.
/// </summary>
void ResolveAssemblyReferences();
} }
/// <summary> /// <summary>

88
src/Main/Base/Project/Src/Project/Items/ReferenceProjectItem.cs

@ -12,6 +12,7 @@ using System.Reflection;
using System.Text; using System.Text;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Project 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}", [LocalizedProperty("${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.LocalCopy}",
Description = "${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.LocalCopy.Description}")] Description = "${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.LocalCopy.Description}")]
public bool Private { public bool CopyLocal {
get { get {
return GetEvaluatedMetadata("Private", !IsGacReference); return GetEvaluatedMetadata(CopyLocalMetadataName, !IsGacReference);
} }
set { set {
SetEvaluatedMetadata("Private", value); SetEvaluatedMetadata(CopyLocalMetadataName, value);
} }
} }
DomAssemblyName assemblyName;
/// <summary>
/// Gets the assembly name.
/// </summary>
[Browsable(false)]
public DomAssemblyName AssemblyName {
get { return assemblyName ?? new DomAssemblyName(Include); }
internal set { assemblyName = value; }
}
[ReadOnly(true)] [ReadOnly(true)]
[LocalizedProperty("${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Name}", [LocalizedProperty("${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Name}",
Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Name.Description}")] Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Name.Description}")]
public string Name { public string Name {
get { get {
AssemblyName assemblyName = GetAssemblyName(Include); return this.AssemblyName.ShortName;
if (assemblyName != null) {
return assemblyName.Name;
}
return Include;
} }
} }
@ -101,11 +111,10 @@ namespace ICSharpCode.SharpDevelop.Project
Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Version.Description}")] Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Version.Description}")]
public Version Version { public Version Version {
get { get {
AssemblyName assemblyName = GetAssemblyName(Include); if (this.AssemblyName.Version == null)
if (assemblyName != null) {
return assemblyName.Version;
}
return 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}")] Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.Culture.Description}")]
public string Culture { public string Culture {
get { get {
AssemblyName assemblyName = GetAssemblyName(Include); return this.AssemblyName.Culture;
if (assemblyName != null && assemblyName.CultureInfo != null) {
return assemblyName.CultureInfo.Name;
}
return null;
} }
} }
@ -127,24 +132,32 @@ namespace ICSharpCode.SharpDevelop.Project
Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.PublicKeyToken.Description}")] Description="${res:ICSharpCode.SharpDevelop.Internal.Project.ProjectReference.PublicKeyToken.Description}")]
public string PublicKeyToken { public string PublicKeyToken {
get { get {
AssemblyName assemblyName = GetAssemblyName(Include); return this.AssemblyName.PublicKeyToken;
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;
} }
string redist;
/// <summary>
/// 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
/// </summary>
[Browsable(false)]
public string Redist {
get { return redist; }
set { redist = value; }
} }
string fullPath;
[ReadOnly(true)] [ReadOnly(true)]
public override string FileName { public override string FileName {
get { get {
if (fullPath != null) {
return fullPath;
}
if (Project != null) { if (Project != null) {
string projectDir = Project.Directory; string projectDir = Project.Directory;
string hintPath = HintPath; string hintPath = HintPath;
@ -167,7 +180,7 @@ namespace ICSharpCode.SharpDevelop.Project
return Include; return Include;
} }
set { 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) protected override void FilterProperties(PropertyDescriptorCollection globalizedProps)
{ {
base.FilterProperties(globalizedProps); base.FilterProperties(globalizedProps);
PropertyDescriptor privatePD = globalizedProps["Private"]; PropertyDescriptor copyLocalPD = globalizedProps["CopyLocal"];
globalizedProps.Remove(privatePD); globalizedProps.Remove(copyLocalPD);
globalizedProps.Add(new ReplaceDefaultValueDescriptor(privatePD, !IsGacReference)); globalizedProps.Add(new ReplaceDefaultValueDescriptor(copyLocalPD, !IsGacReference));
} }
sealed class ReplaceDefaultValueDescriptor : PropertyDescriptor sealed class ReplaceDefaultValueDescriptor : PropertyDescriptor

5
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 #region CreateProjectItem
/// <summary> /// <summary>
/// Creates a new projectItem for the passed itemType /// Creates a new projectItem for the passed itemType

76
src/Main/Base/Project/Src/Project/MSBuildInternals.cs

@ -5,16 +5,18 @@
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
using ICSharpCode.Core;
using System; using System;
using System.Diagnostics; using System.IO;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Diagnostics;
using System.Xml;
using System.Text;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Xml;
using MSBuild = Microsoft.Build.BuildEngine; using MSBuild = Microsoft.Build.BuildEngine;
namespace ICSharpCode.SharpDevelop.Project namespace ICSharpCode.SharpDevelop.Project
@ -229,6 +231,9 @@ namespace ICSharpCode.SharpDevelop.Project
/// </summary> /// </summary>
public static void ClearImports(MSBuild.Project project) public static void ClearImports(MSBuild.Project project)
{ {
if (project == null)
throw new ArgumentNullException("project");
XmlElement xmlProject = BeginXmlManipulation(project); XmlElement xmlProject = BeginXmlManipulation(project);
List<XmlNode> nodesToRemove = new List<XmlNode>(); List<XmlNode> nodesToRemove = new List<XmlNode>();
foreach (XmlNode node in xmlProject.ChildNodes) { foreach (XmlNode node in xmlProject.ChildNodes) {
@ -239,6 +244,7 @@ namespace ICSharpCode.SharpDevelop.Project
foreach (XmlNode node in nodesToRemove) { foreach (XmlNode node in nodesToRemove) {
xmlProject.RemoveChild(node); xmlProject.RemoveChild(node);
} }
EndXmlManipulation(project);
} }
/// <summary> /// <summary>
@ -303,5 +309,67 @@ namespace ICSharpCode.SharpDevelop.Project
null, project, null null, project, null
); );
} }
internal static void ResolveAssemblyReferences(MSBuildBasedProject baseProject, ReferenceProjectItem[] referenceReplacements)
{
MSBuild.Engine engine;
MSBuild.Project tempProject;
IEnumerable<ReferenceProjectItem> references;
lock (baseProject.SyncRoot) {
// create a copy of the project
engine = CreateEngine();
tempProject = engine.CreateNewProject();
// tell MSBuild the path so that projects containing <Import Project="relativePath" />
// 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<ReferenceProjectItem>();
} 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);
}
}
}
} }
} }

69
src/Main/Base/Project/Src/Project/Solution/Solution.cs

@ -12,8 +12,9 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using SearchAndReplace;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using MSBuild = Microsoft.Build.BuildEngine; using MSBuild = Microsoft.Build.BuildEngine;
namespace ICSharpCode.SharpDevelop.Project 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; ProjectSection nestedProjectsSection = null;
bool needsConversion = false; bool needsConversion = false;
// read solution files using system encoding, but detect UTF8 if BOM is present // 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); string line = GetFirstNonCommentLine(sr);
Match match = versionPattern.Match(line); Match match = versionPattern.Match(line);
if (!match.Success) { if (!match.Success) {
MessageService.ShowErrorFormatted("${res:SharpDevelop.Solution.InvalidSolutionFile}", fileName); MessageService.ShowErrorFormatted("${res:SharpDevelop.Solution.InvalidSolutionFile}", newSolution.FileName);
return false; return false;
} }
@ -482,13 +482,43 @@ namespace ICSharpCode.SharpDevelop.Project
return false; return false;
} }
using (AsynchronousWaitDialog waitDialog = AsynchronousWaitDialog.ShowWaitDialog("Loading solution")) {
nestedProjectsSection = SetupSolutionLoadSolutionProjects(newSolution, sr, waitDialog);
}
}
// Create solution folder 'tree'.
if (nestedProjectsSection != null) {
foreach (SolutionItem item in nestedProjectsSection.Items) {
string from = item.Name;
string to = item.Location;
if (newSolution.guidDictionary.ContainsKey(to) && newSolution.guidDictionary.ContainsKey(from)) {
// ignore invalid entries
ISolutionFolderContainer folder = newSolution.guidDictionary[to] as ISolutionFolderContainer;
folder.AddFolder(newSolution.guidDictionary[from]);
}
}
}
if (newSolution.FixSolutionConfiguration(newSolution.Projects) || needsConversion) {
// save in new format
newSolution.Save();
}
return true;
}
static ProjectSection SetupSolutionLoadSolutionProjects(Solution newSolution, StreamReader sr, IProgressMonitor progressMonitor)
{
string solutionDirectory = Path.GetDirectoryName(newSolution.FileName);
ProjectSection nestedProjectsSection = null;
while (true) { while (true) {
line = sr.ReadLine(); string line = sr.ReadLine();
if (line == null) { if (line == null) {
break; break;
} }
match = projectLinePattern.Match(line); Match match = projectLinePattern.Match(line);
if (match.Success) { if (match.Success) {
string projectGuid = match.Result("${ProjectGuid}"); string projectGuid = match.Result("${ProjectGuid}");
string title = match.Result("${Title}"); string title = match.Result("${Title}");
@ -503,7 +533,7 @@ namespace ICSharpCode.SharpDevelop.Project
SolutionFolder newFolder = SolutionFolder.ReadFolder(sr, title, location, guid); SolutionFolder newFolder = SolutionFolder.ReadFolder(sr, title, location, guid);
newSolution.AddFolder(newFolder); newSolution.AddFolder(newFolder);
} else { } else {
IProject newProject = LanguageBindingService.LoadProject(newSolution, location, title, projectGuid); IProject newProject = LanguageBindingService.LoadProject(newSolution, location, title, projectGuid, progressMonitor);
ReadProjectSections(sr, newProject.ProjectSections); ReadProjectSections(sr, newProject.ProjectSections);
newProject.IdGuid = guid; newProject.IdGuid = guid;
newSolution.AddFolder(newProject); newSolution.AddFolder(newProject);
@ -524,26 +554,7 @@ namespace ICSharpCode.SharpDevelop.Project
} }
} }
} }
} return nestedProjectsSection;
// Create solution folder 'tree'.
if (nestedProjectsSection != null) {
foreach (SolutionItem item in nestedProjectsSection.Items) {
string from = item.Name;
string to = item.Location;
if (newSolution.guidDictionary.ContainsKey(to) && newSolution.guidDictionary.ContainsKey(from)) {
// ignore invalid entries
ISolutionFolderContainer folder = newSolution.guidDictionary[to] as ISolutionFolderContainer;
folder.AddFolder(newSolution.guidDictionary[from]);
}
}
}
if (newSolution.FixSolutionConfiguration(newSolution.Projects) || needsConversion) {
// save in new format
newSolution.Save();
}
return true;
} }
#endregion #endregion
@ -1108,7 +1119,7 @@ namespace ICSharpCode.SharpDevelop.Project
} }
} else { } else {
newSolution.fileName = fileName; newSolution.fileName = fileName;
if (!SetupSolution(newSolution, fileName)) { if (!SetupSolution(newSolution)) {
return null; return null;
} }
} }

10
src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingService.cs

@ -5,11 +5,11 @@
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
using ICSharpCode.SharpDevelop.Gui;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Xml; using System.Xml;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
@ -90,10 +90,10 @@ namespace ICSharpCode.SharpDevelop
public static IProject LoadProject(IMSBuildEngineProvider provider, string location, string title) 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) if (provider == null)
throw new ArgumentNullException("provider"); throw new ArgumentNullException("provider");
@ -104,6 +104,10 @@ namespace ICSharpCode.SharpDevelop
if (projectTypeGuid == null) if (projectTypeGuid == null)
throw new ArgumentNullException("projectTypeGuid"); throw new ArgumentNullException("projectTypeGuid");
if (progressMonitor != null) {
progressMonitor.BeginTask("Loading " + title, 0, false);
}
IProject newProject; IProject newProject;
if (!File.Exists(location)) { if (!File.Exists(location)) {
newProject = new MissingProject(location, title); newProject = new MissingProject(location, title);

76
src/Main/Base/Project/Src/Services/ParserService/Net1xProjectContentRegistry.cs

@ -1,76 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.IO;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// Project content registry for .NET 1.0 and .NET 1.1 assemblies.
/// </summary>
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"; }
}
}
}

4
src/Main/Base/Project/Src/Services/ParserService/NetCFProjectContentRegistry.cs

@ -32,7 +32,8 @@ namespace ICSharpCode.SharpDevelop
return null; return null;
} }
/*
Is this still required now that we use MSBuild to resolve assembly references?
protected override IProjectContent LoadProjectContent(string itemInclude, string itemFileName) protected override IProjectContent LoadProjectContent(string itemInclude, string itemFileName)
{ {
if (File.Exists(itemFileName)) { if (File.Exists(itemFileName)) {
@ -70,5 +71,6 @@ namespace ICSharpCode.SharpDevelop
} }
return base.LoadProjectContent(itemInclude, itemFileName); return base.LoadProjectContent(itemInclude, itemFileName);
} }
*/
} }
} }

3
src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

@ -47,6 +47,9 @@ namespace ICSharpCode.SharpDevelop
ProjectService.ProjectItemAdded += OnProjectItemAdded; ProjectService.ProjectItemAdded += OnProjectItemAdded;
ProjectService.ProjectItemRemoved += OnProjectItemRemoved; ProjectService.ProjectItemRemoved += OnProjectItemRemoved;
UpdateDefaultImports(items); UpdateDefaultImports(items);
StatusBarService.ProgressMonitor.BeginTask("Resolving references for " + project.Name, 0, false);
project.ResolveAssemblyReferences();
StatusBarService.ProgressMonitor.Done();
foreach (ProjectItem item in items) { foreach (ProjectItem item in items) {
if (!initializing) return; // abort initialization if (!initializing) return; // abort initialization
if (item.ItemType == ItemType.Reference if (item.ItemType == ItemType.Reference

4
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -126,6 +126,7 @@ namespace ICSharpCode.SharpDevelop
} }
} }
loadSolutionProjectsThread = new Thread(new ThreadStart(LoadSolutionProjects)); loadSolutionProjectsThread = new Thread(new ThreadStart(LoadSolutionProjects));
loadSolutionProjectsThread.SetApartmentState(ApartmentState.STA); // allow loadSolutionProjects thread access to MSBuild
loadSolutionProjectsThread.Name = "loadSolutionProjects"; loadSolutionProjectsThread.Name = "loadSolutionProjects";
loadSolutionProjectsThread.Priority = ThreadPriority.BelowNormal; loadSolutionProjectsThread.Priority = ThreadPriority.BelowNormal;
loadSolutionProjectsThread.IsBackground = true; loadSolutionProjectsThread.IsBackground = true;
@ -280,6 +281,7 @@ namespace ICSharpCode.SharpDevelop
if (reParseThread == null) { if (reParseThread == null) {
LoggingService.Info("Starting reParse thread"); LoggingService.Info("Starting reParse thread");
reParseThread = new Thread(new ThreadStart(ReparseProjects)); reParseThread = new Thread(new ThreadStart(ReparseProjects));
reParseThread.SetApartmentState(ApartmentState.STA); // allow reParseThread access to MSBuild
reParseThread.Name = "reParse"; reParseThread.Name = "reParse";
reParseThread.Priority = ThreadPriority.BelowNormal; reParseThread.Priority = ThreadPriority.BelowNormal;
reParseThread.IsBackground = true; reParseThread.IsBackground = true;
@ -764,7 +766,7 @@ namespace ICSharpCode.SharpDevelop
} }
return ParserService.GetProjectContent(((ProjectReferenceProjectItem)item).ReferencedProject); 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) public static IProjectContent GetProjectContentForReference(ReferenceProjectItem item)

75
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs

@ -69,21 +69,21 @@ namespace ICSharpCode.SharpDevelop.Dom
/// <summary> /// <summary>
/// Gets the full display name of the GAC assembly of the specified short name /// Gets the full display name of the GAC assembly of the specified short name
/// </summary> /// </summary>
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[] info;
string version = name.Version; string version = name.Version;
string publicKey = name.PublicKey; string publicKey = name.PublicKeyToken;
IApplicationContext applicationContext = null; IApplicationContext applicationContext = null;
IAssemblyEnum assemblyEnum = null; IAssemblyEnum assemblyEnum = null;
IAssemblyName assemblyName; 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); Fusion.CreateAssemblyEnum(out assemblyEnum, null, assemblyName, 2, 0);
List<string> names = new List<string>(); List<string> names = new List<string>();
@ -123,7 +123,7 @@ namespace ICSharpCode.SharpDevelop.Dom
} }
} }
if (best != null) if (best != null)
return new GacAssemblyName(best); return new DomAssemblyName(best);
} }
// use assembly with highest version // use assembly with highest version
best = names[0]; best = names[0];
@ -137,68 +137,7 @@ namespace ICSharpCode.SharpDevelop.Dom
best = names[i]; best = names[i];
} }
} }
return new GacAssemblyName(best); return new DomAssemblyName(best);
}
}
public class GacAssemblyName : IEquatable<GacAssemblyName>
{
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();
} }
} }
} }

58
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 /// Similar to System.Reflection.AssemblyName, but does not raise an exception
/// on invalid assembly names. (See SD2-1307) /// on invalid assembly names. (See SD2-1307)
/// </summary> /// </summary>
public sealed class DomAssemblyName public sealed class DomAssemblyName : IEquatable<DomAssemblyName>
{ {
readonly string fullAssemblyName; readonly string fullAssemblyName;
readonly string shortName, version, culture, publicKeyToken;
public DomAssemblyName(string fullAssemblyName) public DomAssemblyName(string fullAssemblyName)
{ {
this.fullAssemblyName = 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 { public string FullName {
get { return fullAssemblyName; } 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) internal static DomAssemblyName[] Convert(System.Reflection.AssemblyName[] names)
{ {
if (names == null) return null; if (names == null) return null;

54
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ProjectContentRegistry.cs

@ -24,11 +24,6 @@ namespace ICSharpCode.SharpDevelop.Dom
internal DomPersistence persistence; internal DomPersistence persistence;
Dictionary<string, IProjectContent> contents = new Dictionary<string, IProjectContent>(StringComparer.InvariantCultureIgnoreCase); Dictionary<string, IProjectContent> contents = new Dictionary<string, IProjectContent>(StringComparer.InvariantCultureIgnoreCase);
/// <summary>
/// Redirects short names to long names. Used to redirect .NET libraries to the chosen .NET version
/// </summary>
protected Dictionary<string, string> redirectedAssemblyNames = new Dictionary<string, string>();
/// <summary> /// <summary>
/// Disposes all project contents stored in this registry. /// Disposes all project contents stored in this registry.
/// </summary> /// </summary>
@ -177,9 +172,6 @@ namespace ICSharpCode.SharpDevelop.Dom
contents["mscorlib"] = mscorlibContent; contents["mscorlib"] = mscorlibContent;
contents[mscorlibContent.AssemblyFullName] = mscorlibContent; contents[mscorlibContent.AssemblyFullName] = mscorlibContent;
contents[mscorlibContent.AssemblyLocation] = mscorlibContent; contents[mscorlibContent.AssemblyLocation] = mscorlibContent;
lock (redirectedAssemblyNames) {
redirectedAssemblyNames.Add("mscorlib", mscorlibContent.AssemblyFullName);
}
return mscorlibContent; return mscorlibContent;
} }
} }
@ -218,31 +210,14 @@ namespace ICSharpCode.SharpDevelop.Dom
public IProjectContent GetExistingProjectContent(DomAssemblyName assembly) 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) { lock (contents) {
if (contents.ContainsKey(itemFileName)) { if (contents.ContainsKey(fileNameOrAssemblyName)) {
return contents[itemFileName]; return contents[fileNameOrAssemblyName];
}
if (contents.ContainsKey(itemInclude)) {
return contents[itemInclude];
} }
} }
return null; return null;
@ -251,7 +226,7 @@ namespace ICSharpCode.SharpDevelop.Dom
public virtual IProjectContent GetProjectContentForReference(string itemInclude, string itemFileName) public virtual IProjectContent GetProjectContentForReference(string itemInclude, string itemFileName)
{ {
lock (contents) { lock (contents) {
IProjectContent pc = GetExistingProjectContent(itemInclude, itemFileName); IProjectContent pc = GetExistingProjectContent(itemFileName);
if (pc != null) { if (pc != null) {
return pc; return pc;
} }
@ -310,26 +285,19 @@ namespace ICSharpCode.SharpDevelop.Dom
persistence.SaveProjectContent(pc); 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 { } else {
// find real file name for cecil: // find real file name for cecil:
if (File.Exists(itemFileName)) { if (File.Exists(itemFileName)) {
pc = CecilReader.LoadAssembly(itemFileName, this); pc = CecilReader.LoadAssembly(itemFileName, this);
} else { } else {
GacAssemblyName asmName = GacInterop.FindBestMatchingAssemblyName(itemInclude); DomAssemblyName asmName = GacInterop.FindBestMatchingAssemblyName(itemInclude);
if (persistence != null && asmName != null) { if (persistence != null && asmName != null) {
//LoggingService.Debug("Looking up in DOM cache: " + asmName.FullName); //LoggingService.Debug("Looking up in DOM cache: " + asmName.FullName);
pc = persistence.LoadProjectContentByAssemblyName(asmName.FullName); pc = persistence.LoadProjectContentByAssemblyName(asmName.FullName);
} }
if (pc == null && asmName != null) { if (pc == null && asmName != null) {
string subPath = Path.Combine(asmName.Name, GetVersion__Token(asmName)); string subPath = Path.Combine(asmName.ShortName, GetVersion__Token(asmName));
subPath = Path.Combine(subPath, asmName.Name + ".dll"); subPath = Path.Combine(subPath, asmName.ShortName + ".dll");
foreach (string dir in Directory.GetDirectories(GacInterop.GacRootPath, "GAC*")) { foreach (string dir in Directory.GetDirectories(GacInterop.GacRootPath, "GAC*")) {
itemFileName = Path.Combine(dir, subPath); itemFileName = Path.Combine(dir, subPath);
if (File.Exists(itemFileName)) { if (File.Exists(itemFileName)) {
@ -342,18 +310,18 @@ namespace ICSharpCode.SharpDevelop.Dom
} }
} }
if (pc == null) { if (pc == null) {
HostCallback.ShowAssemblyLoadErrorInternal("?", itemInclude, "Could not find assembly file."); HostCallback.ShowAssemblyLoadErrorInternal(itemFileName, itemInclude, "Could not find assembly file.");
} }
} }
} }
return pc; return pc;
} }
static string GetVersion__Token(GacAssemblyName asmName) static string GetVersion__Token(DomAssemblyName asmName)
{ {
StringBuilder b = new StringBuilder(asmName.Version.ToString()); StringBuilder b = new StringBuilder(asmName.Version.ToString());
b.Append("__"); b.Append("__");
b.Append(asmName.PublicKey); b.Append(asmName.PublicKeyToken);
return b.ToString(); return b.ToString();
} }

4
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) public static Assembly ReflectionLoadGacAssembly(string partialName, bool reflectionOnly)
{ {
if (reflectionOnly) { if (reflectionOnly) {
GacAssemblyName name = GacInterop.FindBestMatchingAssemblyName(partialName); DomAssemblyName name = GacInterop.FindBestMatchingAssemblyName(partialName);
if (name == null) if (name == null)
return null; return null;
return Assembly.ReflectionOnlyLoad(name.FullName); return Assembly.ReflectionOnlyLoad(name.FullName);
@ -98,7 +98,7 @@ namespace ICSharpCode.SharpDevelop.Dom
LoggingService.Warn("AssemblyResolve: ReflectionOnlyLoad failed for " + e.Name); LoggingService.Warn("AssemblyResolve: ReflectionOnlyLoad failed for " + e.Name);
// We can't get the assembly we want. // We can't get the assembly we want.
// But propably we can get a similar version of it. // 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); LoggingService.Info("AssemblyResolve: FixedName: " + fixedName);
return Assembly.ReflectionOnlyLoad(fixedName.FullName); return Assembly.ReflectionOnlyLoad(fixedName.FullName);
} }

Loading…
Cancel
Save