Browse Source

Fix SD-1872 - Forms Designer is unbearably slow in 4.2

pull/21/merge
Daniel Grunwald 14 years ago
parent
commit
68f75c067b
  1. 4
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs
  2. 14
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs
  3. 76
      src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyController.cs
  4. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/IdeChooseClassService.cs
  5. 89
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/GacInterop.cs
  6. 42
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs

4
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs

@ -77,9 +77,7 @@ namespace ICSharpCode.FormsDesigner.Gui @@ -77,9 +77,7 @@ namespace ICSharpCode.FormsDesigner.Gui
ReflectionProjectContent rpc = pc as ReflectionProjectContent;
if (rpc == null)
continue;
if (rpc.AssemblyFullName == typeof(object).Assembly.FullName)
continue;
if (GacInterop.IsWithinGac(rpc.AssemblyLocation))
if (rpc.IsGacAssembly)
continue;
}
foreach (IClass c in pc.Classes) {

14
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs

@ -109,18 +109,18 @@ namespace ICSharpCode.FormsDesigner.Services @@ -109,18 +109,18 @@ namespace ICSharpCode.FormsDesigner.Services
this.formSourceFileName = formSourceFileName;
}
static readonly Dictionary<IProjectContent, object> projectContentsCurrentlyLoadingAssembly = new Dictionary<IProjectContent, object>();
readonly HashSet<IProjectContent> projectContentsCurrentlyLoadingAssembly = new HashSet<IProjectContent>();
/// <summary>
/// Loads the assembly represented by the project content. Returns null on failure.
/// </summary>
public Assembly LoadAssembly(IProjectContent pc)
{
WorkbenchSingleton.AssertMainThread();
// prevent StackOverflow when project contents have cyclic dependencies
// Very popular example of cyclic dependency: System <-> System.Xml (yes, really!)
if (projectContentsCurrentlyLoadingAssembly.ContainsKey(pc))
// Very popular example of cyclic dependency: System <-> System.Xml
if (!projectContentsCurrentlyLoadingAssembly.Add(pc))
return null;
projectContentsCurrentlyLoadingAssembly.Add(pc, null);
try {
// load dependencies of current assembly
@ -129,9 +129,7 @@ namespace ICSharpCode.FormsDesigner.Services @@ -129,9 +129,7 @@ namespace ICSharpCode.FormsDesigner.Services
LoadAssembly(rpc);
} else if (rpc is ReflectionProjectContent) {
ReflectionProjectContent rrpc = (ReflectionProjectContent)rpc;
if (rrpc.AssemblyFullName != typeof(object).FullName
&& !GacInterop.IsWithinGac(rrpc.AssemblyLocation))
{
if (!rrpc.IsGacAssembly) {
LoadAssembly(rpc);
}
}
@ -144,7 +142,7 @@ namespace ICSharpCode.FormsDesigner.Services @@ -144,7 +142,7 @@ namespace ICSharpCode.FormsDesigner.Services
return LoadAssembly(((IProject)pc.Project).OutputAssemblyFullPath);
} else if (pc is ReflectionProjectContent) {
ReflectionProjectContent rpc = (ReflectionProjectContent)pc;
if (GacInterop.IsWithinGac(rpc.AssemblyLocation))
if (rpc.IsGacAssembly)
return LoadAssembly(new AssemblyName(rpc.AssemblyFullName), false);
else
return LoadAssembly(rpc.AssemblyLocation);

76
src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyController.cs

@ -59,12 +59,7 @@ namespace ICSharpCode.ILSpyAddIn @@ -59,12 +59,7 @@ namespace ICSharpCode.ILSpyAddIn
if (rpc == null)
throw new ArgumentNullException("rpc");
// prefer GAC assemblies over reference assemblies:
string assemblyLocation = FindAssemblyInNetGac(new DomAssemblyName(rpc.AssemblyFullName));
if (string.IsNullOrEmpty(assemblyLocation)) {
// use file only if assembly isn't in GAC:
assemblyLocation = rpc.AssemblyLocation;
}
return assemblyLocation;
return rpc.RealAssemblyLocation;
}
#region Find ILSpy
@ -103,74 +98,5 @@ namespace ICSharpCode.ILSpyAddIn @@ -103,74 +98,5 @@ namespace ICSharpCode.ILSpyAddIn
return path;
}
#endregion
#region FindAssemblyInGac
// This region is based on code from Mono.Cecil:
// Author:
// Jb Evain (jbevain@gmail.com)
//
// Copyright (c) 2008 - 2010 Jb Evain
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
static readonly string[] gac_paths = { GacInterop.GacRootPathV2, GacInterop.GacRootPathV4 };
static readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" };
static readonly string[] prefixes = { string.Empty, "v4.0_" };
/// <summary>
/// Gets the file name for an assembly stored in the GAC.
/// </summary>
public static string FindAssemblyInNetGac (DomAssemblyName reference)
{
// without public key, it can't be in the GAC
if (reference.PublicKeyToken == null)
return null;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < gacs.Length; j++) {
var gac = Path.Combine (gac_paths [i], gacs [j]);
var file = GetAssemblyFile (reference, prefixes [i], gac);
if (File.Exists (file))
return file;
}
}
return null;
}
static string GetAssemblyFile (DomAssemblyName reference, string prefix, string gac)
{
var gac_folder = new StringBuilder ()
.Append (prefix)
.Append (reference.Version)
.Append ("__");
gac_folder.Append (reference.PublicKeyToken);
return Path.Combine (
Path.Combine (
Path.Combine (gac, reference.ShortName), gac_folder.ToString ()),
reference.ShortName + ".dll");
}
#endregion
}
}

2
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/IdeChooseClassService.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.WpfDesign.AddIn @@ -20,7 +20,7 @@ namespace ICSharpCode.WpfDesign.AddIn
{
var r = projectContent as ReflectionProjectContent;
if (r != null) {
return r.AssemblyLocation;
return r.RealAssemblyLocation;
}
var p = projectContent.Project as IProject;
if (p != null) {

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

@ -3,9 +3,9 @@ @@ -3,9 +3,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using MSjogren.GacTool.FusionNative;
namespace ICSharpCode.SharpDevelop.Dom
@ -16,25 +16,15 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -16,25 +16,15 @@ namespace ICSharpCode.SharpDevelop.Dom
/// </summary>
public static class GacInterop
{
volatile static string cachedGacPathV2;
volatile static string cachedGacPathV4;
static readonly string cachedGacPathV2 = Fusion.GetGacPath(false);
static readonly string cachedGacPathV4 = Fusion.GetGacPath(true);
public static string GacRootPathV2 {
get {
if (cachedGacPathV2 == null) {
cachedGacPathV2 = Fusion.GetGacPath(false);
}
return cachedGacPathV2;
}
get { return cachedGacPathV2; }
}
public static string GacRootPathV4 {
get {
if (cachedGacPathV4 == null) {
cachedGacPathV4 = Fusion.GetGacPath(true);
}
return cachedGacPathV4;
}
get { return cachedGacPathV4; }
}
public static bool IsWithinGac(string assemblyLocation)
@ -135,5 +125,74 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -135,5 +125,74 @@ namespace ICSharpCode.SharpDevelop.Dom
}
return new DomAssemblyName(best);
}
#region FindAssemblyInGac
// This region is based on code from Mono.Cecil:
// Author:
// Jb Evain (jbevain@gmail.com)
//
// Copyright (c) 2008 - 2010 Jb Evain
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
static readonly string[] gac_paths = { GacInterop.GacRootPathV2, GacInterop.GacRootPathV4 };
static readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" };
static readonly string[] prefixes = { string.Empty, "v4.0_" };
/// <summary>
/// Gets the file name for an assembly stored in the GAC.
/// </summary>
public static string FindAssemblyInNetGac (DomAssemblyName reference)
{
// without public key, it can't be in the GAC
if (reference.PublicKeyToken == null)
return null;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < gacs.Length; j++) {
var gac = Path.Combine (gac_paths [i], gacs [j]);
var file = GetAssemblyFile (reference, prefixes [i], gac);
if (File.Exists (file))
return file;
}
}
return null;
}
static string GetAssemblyFile (DomAssemblyName reference, string prefix, string gac)
{
var gac_folder = new StringBuilder ()
.Append (prefix)
.Append (reference.Version)
.Append ("__");
gac_folder.Append (reference.PublicKeyToken);
return Path.Combine (
Path.Combine (
Path.Combine (gac, reference.ShortName), gac_folder.ToString ()),
reference.ShortName + ".dll");
}
#endregion
}
}

42
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/ReflectionProjectContent.cs

@ -19,22 +19,64 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -19,22 +19,64 @@ namespace ICSharpCode.SharpDevelop.Dom
string assemblyLocation;
ProjectContentRegistry registry;
/// <summary>
/// Gets the file path to the (reference) assembly.
/// </summary>
public string AssemblyLocation {
get {
return assemblyLocation;
}
}
/// <summary>
/// Gets the full assembly name (e.g. "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
/// </summary>
public string AssemblyFullName {
get {
return assemblyFullName;
}
}
/// <summary>
/// Gets the short assembly name (e.g. "System")
/// </summary>
public override string AssemblyName {
get { return assemblyName; }
}
volatile string assemblyLocationInGAC;
string GetAssemblyLocationInGAC()
{
if (assemblyLocationInGAC == null) {
assemblyLocationInGAC = GacInterop.FindAssemblyInNetGac(new DomAssemblyName(assemblyFullName)) ?? string.Empty;
}
return assemblyLocationInGAC;
}
/// <summary>
/// Gets the real assembly location.
/// For reference assemblies of GAC assemblies, this is the assembly in the GAC.
/// Otherwise, this is the same as AssemblyLocation.
/// </summary>
public string RealAssemblyLocation {
get {
string gacAssembly = GetAssemblyLocationInGAC();
if (string.IsNullOrEmpty(gacAssembly))
return this.AssemblyLocation;
else
return gacAssembly;
}
}
/// <summary>
/// Gets whether this assembly is available in the GAC.
/// This property also returns true for reference assemblies when the corresponding real assembly is available in the GAC.
/// </summary>
public bool IsGacAssembly {
get { return !string.IsNullOrEmpty(GetAssemblyLocationInGAC()); }
}
/// <summary>
/// Gets the list of assembly names referenced by this project content.
/// </summary>

Loading…
Cancel
Save