Skip to content

Commit 0b6080b

Browse files
author
Stephan
committed
Improve handling of VS projects (IObjectWithSite)
1 parent 0a7ad13 commit 0b6080b

File tree

6 files changed

+147
-52
lines changed

6 files changed

+147
-52
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using Microsoft.VisualStudio;
4+
using Microsoft.VisualStudio.Shell.Interop;
5+
6+
namespace Zbu.ModelsBuilder.CustomTool.CustomTool
7+
{
8+
// note: see https://github.com/RazorGenerator/RazorGenerator
9+
10+
[ComVisible(true)]
11+
public abstract class BaseCodeGenerator : IVsSingleFileGenerator
12+
{
13+
#region IVsSingleFileGenerator Members
14+
15+
int IVsSingleFileGenerator.DefaultExtension(out string pbstrDefaultExtension)
16+
{
17+
try
18+
{
19+
pbstrDefaultExtension = GetDefaultExtension();
20+
return VSConstants.S_OK;
21+
}
22+
catch (Exception e)
23+
{
24+
pbstrDefaultExtension = string.Empty;
25+
return VSConstants.E_FAIL;
26+
}
27+
}
28+
29+
int IVsSingleFileGenerator.Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
30+
{
31+
if (bstrInputFileContents == null)
32+
throw new ArgumentNullException("bstrInputFileContents");
33+
return Generate(wszInputFilePath, bstrInputFileContents, wszDefaultNamespace, rgbOutputFileContents, out pcbOutput, pGenerateProgress);
34+
}
35+
36+
#endregion
37+
38+
protected abstract string GetDefaultExtension();
39+
40+
protected abstract int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress);
41+
}
42+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using EnvDTE;
4+
using Microsoft.VisualStudio;
5+
using Microsoft.VisualStudio.Shell;
6+
using VSOLE = Microsoft.VisualStudio.OLE.Interop;
7+
8+
namespace Zbu.ModelsBuilder.CustomTool.CustomTool
9+
{
10+
// note: see https://github.com/RazorGenerator/RazorGenerator
11+
12+
[ComVisible(true)]
13+
public abstract class BaseCodeGeneratorWithSite : BaseCodeGenerator, VSOLE.IObjectWithSite
14+
{
15+
private object _site;
16+
private ServiceProvider _serviceProvider;
17+
18+
#region IObjectWithSite Members
19+
20+
21+
void VSOLE.IObjectWithSite.GetSite(ref Guid riid, out IntPtr ppvSite)
22+
{
23+
if (_site == null)
24+
throw new COMException("object is not sited", VSConstants.E_FAIL);
25+
26+
var pUnknownPointer = Marshal.GetIUnknownForObject(_site);
27+
IntPtr intPointer; // = IntPtr.Zero;
28+
Marshal.QueryInterface(pUnknownPointer, ref riid, out intPointer);
29+
30+
if (intPointer == IntPtr.Zero)
31+
throw new COMException("site does not support requested interface", VSConstants.E_NOINTERFACE);
32+
33+
ppvSite = intPointer;
34+
}
35+
36+
void VSOLE.IObjectWithSite.SetSite(object pUnkSite)
37+
{
38+
_site = pUnkSite;
39+
}
40+
41+
#endregion
42+
43+
private ServiceProvider SiteServiceProvider
44+
{
45+
get {
46+
return _serviceProvider ?? (_serviceProvider = new ServiceProvider(_site as VSOLE.IServiceProvider));
47+
}
48+
}
49+
50+
protected object GetService(Type serviceType)
51+
{
52+
return SiteServiceProvider.GetService(serviceType);
53+
}
54+
55+
protected ProjectItem GetProjectItem()
56+
{
57+
var p = GetService(typeof (ProjectItem));
58+
//Debug.Assert(p != null, "Unable to get Project Item.");
59+
return (ProjectItem) p;
60+
}
61+
62+
protected Project GetProject()
63+
{
64+
return GetProjectItem().ContainingProject;
65+
}
66+
}
67+
}
Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
using System.Runtime.InteropServices;
2-
using Microsoft.CSharp;
32

43
namespace Zbu.ModelsBuilder.CustomTool.CustomTool
54
{
65
[Guid("98983F6D-BC77-46AC-BA5A-8D9E8763F0D2")]
76
[ComVisible(true)]
87
public class ZbuCSharpModelsBuilder : ZbuModelsBuilder
98
{
10-
public ZbuCSharpModelsBuilder()
11-
//: base(new CSharpCodeProvider())
12-
{
13-
}
9+
//public ZbuCSharpModelsBuilder()
10+
// : base(new CSharpCodeProvider())
11+
//{ }
1412

15-
public override int DefaultExtension(out string pbstrDefaultExtension)
13+
protected override string GetDefaultExtension()
1614
{
17-
pbstrDefaultExtension = ".generated.cs";
18-
return 0;
15+
return ".generated.cs";
1916
}
2017
}
2118
}

Zbu.ModelsBuilder.CustomTool/CustomTool/ZbuModelsBuilder.cs

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,11 @@
1010
namespace Zbu.ModelsBuilder.CustomTool.CustomTool
1111
{
1212
[ComVisible(true)]
13-
public abstract class ZbuModelsBuilder : IVsSingleFileGenerator
14-
{
15-
//private readonly CodeDomProvider _codeDomProvider;
16-
//private readonly TypeAttributes? _classAccessibility;
17-
18-
//protected ZbuModelsBuilder(CodeDomProvider codeDomProvider, TypeAttributes? classAccessibility = null*)
19-
//{
20-
// this._codeDomProvider = codeDomProvider;
21-
// this._classAccessibility = classAccessibility;
22-
//}
23-
13+
public abstract class ZbuModelsBuilder : BaseCodeGeneratorWithSite
14+
{
2415
#region IVsSingleFileGenerator Members
2516

26-
public abstract int DefaultExtension(out string pbstrDefaultExtension);
27-
28-
public virtual int Generate(string wszInputFilePath,
17+
protected override int Generate(string wszInputFilePath,
2918
string bstrInputFileContents,
3019
string wszDefaultNamespace,
3120
IntPtr[] rgbOutputFileContents,
@@ -42,7 +31,7 @@ public virtual int Generate(string wszInputFilePath,
4231

4332
// wraps GenerateRaw in a message pump so that Visual Studio
4433
// will display the nice "waiting" modal window...
45-
private static int GenerateWithPump(string wszInputFilePath,
34+
private int GenerateWithPump(string wszInputFilePath,
4635
//string bstrInputFileContents,
4736
string wszDefaultNamespace,
4837
IntPtr[] rgbOutputFileContents,
@@ -74,7 +63,7 @@ private static int GenerateWithPump(string wszInputFilePath,
7463
return rc;
7564
}
7665

77-
private static int GenerateRaw(string wszInputFilePath,
66+
private int GenerateRaw(string wszInputFilePath,
7867
//string bstrInputFileContents,
7968
string wszDefaultNamespace,
8069
IntPtr[] rgbOutputFileContents,
@@ -112,7 +101,9 @@ private static int GenerateRaw(string wszInputFilePath,
112101
VisualStudioHelper.ReportMessage("Found {0} content types in Umbraco.", modelTypes.Count);
113102
*/
114103

115-
var vsitem = VisualStudioHelper.GetSourceItem(wszInputFilePath);
104+
// GetSourceItem was an endless source of confusion - this should be better
105+
//var vsitem = VisualStudioHelper.GetSourceItem(wszInputFilePath);
106+
var vsitem = GetProjectItem();
116107
VisualStudioHelper.ClearExistingItems(vsitem);
117108

118109
foreach (var file in Directory.GetFiles(path, "*.generated.cs"))

Zbu.ModelsBuilder.CustomTool/VisualStudio/VisualStudioHelper.cs

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,28 @@ namespace Zbu.ModelsBuilder.CustomTool.VisualStudio
1010
{
1111
class VisualStudioHelper
1212
{
13-
// ISSUE see GetSourceItem below, this works on the "current" project
13+
// GetSourceItem was an endless source of confusion
1414

15-
//public static string GetProjectBin(string hint)
16-
//{
17-
// if (Path.IsPathRooted(hint)) return hint;
18-
19-
// var dte = (EnvDTE.DTE)Package.GetGlobalService(typeof(EnvDTE.DTE));
20-
// var dteProjects = (Array)dte.ActiveSolutionProjects;
21-
// if (dteProjects.Length <= 0)
22-
// throw new Exception("Panic: no projets.");
23-
24-
// var dteProject = (EnvDTE.Project)dteProjects.GetValue(0);
25-
26-
// var proj = dteProject.FullName; // full path and name of the Project object's file
27-
// var opath = string.IsNullOrWhiteSpace(hint)
28-
// ? dteProject.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString()
29-
// : hint;
30-
// var dir = Path.GetDirectoryName(proj);
31-
// if (dir == null)
32-
// throw new Exception("Panic: null directory name.");
33-
// return Path.Combine(dir, opath);
34-
//}
15+
/*
3516
3617
private static readonly string[] ExcludedProjectKinds =
3718
{
3819
EnvDTE.Constants.vsProjectKindSolutionItems.ToLowerInvariant(), // see [#49]
3920
"{E24C65DC-7377-472B-9ABA-BC803B73C61A}".ToLowerInvariant(), // see [#31]
4021
};
4122
23+
private static string GetProjectName(EnvDTE.Project project)
24+
{
25+
try
26+
{
27+
return project.Name;
28+
}
29+
catch
30+
{
31+
return "(throws)";
32+
}
33+
}
34+
4235
public static EnvDTE.ProjectItem GetSourceItem(string inputFilePath)
4336
{
4437
var dte = (EnvDTE.DTE)Package.GetGlobalService(typeof(EnvDTE.DTE));
@@ -54,8 +47,8 @@ public static EnvDTE.ProjectItem GetSourceItem(string inputFilePath)
5447
var exclude = ExcludedProjectKinds.Contains(p.Kind.ToLowerInvariant());
5548
if (!exclude) return true;
5649
57-
var msg = string.Format("Skipping project \"{0}\" at \"{1}\" of kind \"{2}\" (excluded kind).",
58-
p.FullName, p.FileName, p.Kind);
50+
var msg = string.Format("Skipping project at \"{0}\" named \"{1}\" of kind \"{2}\" (excluded kind).",
51+
p.FileName, GetProjectName(p), p.Kind);
5952
ReportMessage(msg);
6053
return false;
6154
})
@@ -65,8 +58,8 @@ public static EnvDTE.ProjectItem GetSourceItem(string inputFilePath)
6558
var exclude = string.IsNullOrWhiteSpace(p.FileName);
6659
if (!exclude) return true;
6760
68-
var msg = string.Format("Skipping project \"{0}\" at \"{1}\" of kind \"{2}\" (empty filename).",
69-
p.FullName, p.FileName, p.Kind);
61+
var msg = string.Format("Skipping project at \"{0}\" named \"{1}\" of kind \"{2}\" (empty filename).",
62+
p.FileName, GetProjectName(p), p.Kind);
7063
ReportMessage(msg);
7164
return false;
7265
})
@@ -79,8 +72,8 @@ public static EnvDTE.ProjectItem GetSourceItem(string inputFilePath)
7972
}
8073
catch (Exception e)
8174
{
82-
var errmsg = string.Format("Failed to process project \"{0}\" at \"{1}\" of kind \"{2}\" (see inner exception).",
83-
x.FullName, x.FileName, x.Kind);
75+
var errmsg = string.Format("Failed to process project at \"{0}\" named \"{1}\" of kind \"{2}\" (see inner exception).",
76+
x.FileName, GetProjectName(x), x.Kind);
8477
8578
// what shall we do? throwing is not nice neither required, but it's the
8679
// only way we can add project kinds to our exclude list... for the time
@@ -118,6 +111,7 @@ public static EnvDTE.ProjectItem GetSourceItem(string inputFilePath)
118111
119112
return sourceItem;
120113
}
114+
*/
121115

122116
public static void ClearExistingItems(EnvDTE.ProjectItem sourceItem)
123117
{
@@ -137,6 +131,7 @@ public static void AddGeneratedItem(EnvDTE.ProjectItem sourceItem, string filena
137131
newItem.Properties.Item("BuildAction").Value = 1;
138132
}
139133

134+
/*
140135
private static IVsHierarchy ToHierarchy(EnvDTE.Project project)
141136
{
142137
if (project == null || string.IsNullOrWhiteSpace(project.FileName))
@@ -170,6 +165,7 @@ private static IVsHierarchy ToHierarchy(EnvDTE.Project project)
170165
IServiceProvider serviceProvider = new ServiceProvider(project.DTE as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
171166
return VsShellUtilities.GetHierarchy(serviceProvider, new Guid(projectGuid));
172167
}
168+
*/
173169

174170
// see http://msdn.microsoft.com/fr-fr/library/microsoft.visualstudio.shell.interop.ivsgeneratorprogress.generatorerror%28v=vs.90%29.aspx
175171
// level is ignored, line should be -1 if not specified

Zbu.ModelsBuilder.CustomTool/Zbu.ModelsBuilder.CustomTool.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@
148148
<Compile Include="..\Zbu.ModelsBuilder\Properties\CommonInfo.cs">
149149
<Link>Properties\CommonInfo.cs</Link>
150150
</Compile>
151+
<Compile Include="CustomTool\BaseCodeGenerator.cs" />
152+
<Compile Include="CustomTool\BaseCodeGeneratorWithSite.cs" />
151153
<Compile Include="CustomTool\ZbuModelsBuilder.cs" />
152154
<Compile Include="CustomTool\ZbuCSharpModelsBuilder.cs" />
153155
<Compile Include="Guids.cs" />

0 commit comments

Comments
 (0)