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 18 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. 92
      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. 105
      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 @@ @@ -48,7 +48,9 @@
<Reference Include="System.Web.Services" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Framework">
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Build.Engine" />
</ItemGroup>
<ItemGroup>
@ -681,7 +683,6 @@ @@ -681,7 +683,6 @@
<Compile Include="Src\Services\ParserService\Doozer\ProjectContentRegistryDescriptor.cs" />
<Compile Include="Src\Services\ParserService\Doozer\ProjectContentRegistryDoozer.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\Gui\Dialogs\SolutionConfiguration\SolutionConfigurationEditor.Designer.cs">
<DependentUpon>SolutionConfigurationEditor.cs</DependentUpon>

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

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

2
src/Main/Base/Project/Src/Project/BuildTarget.cs

@ -20,6 +20,8 @@ namespace ICSharpCode.SharpDevelop.Project @@ -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;

6
src/Main/Base/Project/Src/Project/IProject.cs

@ -216,6 +216,12 @@ namespace ICSharpCode.SharpDevelop.Project @@ -216,6 +216,12 @@ namespace ICSharpCode.SharpDevelop.Project
/// Gets the minimum version the solution must have to support this project type.
/// </summary>
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>

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

@ -12,6 +12,7 @@ using System.Reflection; @@ -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 @@ -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;
/// <summary>
/// Gets the assembly name.
/// </summary>
[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 @@ -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 @@ -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 @@ -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;
/// <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)]
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 @@ -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 @@ -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

5
src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs

@ -74,6 +74,11 @@ namespace ICSharpCode.SharpDevelop.Project @@ -74,6 +74,11 @@ namespace ICSharpCode.SharpDevelop.Project
}
}
public override void ResolveAssemblyReferences()
{
MSBuildInternals.ResolveAssemblyReferences(this, null);
}
#region CreateProjectItem
/// <summary>
/// Creates a new projectItem for the passed itemType

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

@ -5,16 +5,18 @@ @@ -5,16 +5,18 @@
// <version>$Revision$</version>
// </file>
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 @@ -229,6 +231,9 @@ namespace ICSharpCode.SharpDevelop.Project
/// </summary>
public static void ClearImports(MSBuild.Project project)
{
if (project == null)
throw new ArgumentNullException("project");
XmlElement xmlProject = BeginXmlManipulation(project);
List<XmlNode> nodesToRemove = new List<XmlNode>();
foreach (XmlNode node in xmlProject.ChildNodes) {
@ -239,6 +244,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -239,6 +244,7 @@ namespace ICSharpCode.SharpDevelop.Project
foreach (XmlNode node in nodesToRemove) {
xmlProject.RemoveChild(node);
}
EndXmlManipulation(project);
}
/// <summary>
@ -303,5 +309,67 @@ namespace ICSharpCode.SharpDevelop.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<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);
}
}
}
}
}

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

@ -12,8 +12,9 @@ using System.IO; @@ -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 @@ -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 @@ -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 @@ -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 @@ -1108,7 +1119,7 @@ namespace ICSharpCode.SharpDevelop.Project
}
} else {
newSolution.fileName = fileName;
if (!SetupSolution(newSolution, fileName)) {
if (!SetupSolution(newSolution)) {
return null;
}
}

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

@ -5,11 +5,11 @@ @@ -5,11 +5,11 @@
// <version>$Revision$</version>
// </file>
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 @@ -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 @@ -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);

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

@ -1,76 +0,0 @@ @@ -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 @@ -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 @@ -70,5 +71,6 @@ namespace ICSharpCode.SharpDevelop
}
return base.LoadProjectContent(itemInclude, itemFileName);
}
*/
}
}

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

@ -47,6 +47,9 @@ namespace ICSharpCode.SharpDevelop @@ -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

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

@ -126,6 +126,7 @@ namespace ICSharpCode.SharpDevelop @@ -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 @@ -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 @@ -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)

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

@ -69,21 +69,21 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -69,21 +69,21 @@ namespace ICSharpCode.SharpDevelop.Dom
/// <summary>
/// Gets the full display name of the GAC assembly of the specified short name
/// </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 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<string> names = new List<string>();
@ -123,7 +123,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -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 @@ -137,68 +137,7 @@ namespace ICSharpCode.SharpDevelop.Dom
best = names[i];
}
}
return new GacAssemblyName(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();
return new DomAssemblyName(best);
}
}
}

58
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DomAssemblyName.cs

@ -13,19 +13,75 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -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)
/// </summary>
public sealed class DomAssemblyName
public sealed class DomAssemblyName : IEquatable<DomAssemblyName>
{
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;

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

@ -24,11 +24,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -24,11 +24,6 @@ namespace ICSharpCode.SharpDevelop.Dom
internal DomPersistence persistence;
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>
/// Disposes all project contents stored in this registry.
/// </summary>
@ -177,9 +172,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -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 @@ -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 @@ -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 @@ -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 @@ -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();
}

4
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionLoader.cs

@ -21,7 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -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 @@ -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);
}

Loading…
Cancel
Save