Skip to content

Commit ed1938e

Browse files
committed
code generator can now deal with being called from the IDE first when no xml exists in build/output
1 parent 5593f48 commit ed1938e

File tree

2 files changed

+124
-102
lines changed

2 files changed

+124
-102
lines changed

src/CodeGeneration/DocGenerator/AsciiDoc/GeneratedAsciidocVisitor.cs

Lines changed: 123 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ namespace DocGenerator.AsciiDoc
2929
/// </summary>
3030
public class GeneratedAsciidocVisitor : NoopVisitor
3131
{
32-
private static readonly Dictionary<string,string> Ids = new Dictionary<string, string>();
32+
private static readonly Dictionary<string, string> Ids = new Dictionary<string, string>();
3333

3434
private readonly FileInfo _source;
3535
private readonly FileInfo _destination;
36-
private readonly Dictionary<string, Project> _projects;
37-
private int _topSectionTitleLevel;
36+
private readonly Dictionary<string, Project> _projects;
37+
private int _topSectionTitleLevel;
3838
private Document _document;
3939
private Document _newDocument;
4040
private bool _topLevel = true;
@@ -43,7 +43,7 @@ public GeneratedAsciidocVisitor(FileInfo source, FileInfo destination, Dictionar
4343
{
4444
_source = source;
4545
_destination = destination;
46-
_projects = projects;
46+
_projects = projects;
4747
}
4848

4949
public Document Convert(Document document)
@@ -76,7 +76,8 @@ public override void Visit(Document document)
7676

7777
if (document.Attributes.All(a => a.Name != "ref_current"))
7878
{
79-
_newDocument.Attributes.Add(new AttributeEntry("ref_current", "https://www.elastic.co/guide/en/elasticsearch/reference/6.1"));
79+
_newDocument.Attributes.Add(new AttributeEntry("ref_current",
80+
"https://www.elastic.co/guide/en/elasticsearch/reference/6.1"));
8081
}
8182

8283
var github = "https://github.com/elastic/elasticsearch-net";
@@ -90,18 +91,19 @@ public override void Visit(Document document)
9091
_newDocument.Attributes.Add(new AttributeEntry("nuget", "https://www.nuget.org/packages"));
9192
}
9293

93-
var originalFile = Regex.Replace(_source.FullName.Replace("\\", "/"), @"^(.*Tests/)", $"{github}/tree/master/src/Tests/");
94+
var originalFile = Regex.Replace(_source.FullName.Replace("\\", "/"), @"^(.*Tests/)",
95+
$"{github}/tree/master/src/Tests/");
9496
_newDocument.Insert(0, new Comment
9597
{
9698
Style = CommentStyle.MultiLine,
9799
Text = $"IMPORTANT NOTE\r\n==============\r\nThis file has been generated from {originalFile}. \r\n" +
98-
"If you wish to submit a PR for any spelling mistakes, typos or grammatical errors for this file,\r\n" +
99-
"please modify the original csharp file found at the link and submit the PR with that change. Thanks!"
100+
"If you wish to submit a PR for any spelling mistakes, typos or grammatical errors for this file,\r\n" +
101+
"please modify the original csharp file found at the link and submit the PR with that change. Thanks!"
100102
});
101103

102104
_topSectionTitleLevel = _source.Directory.Name.Equals("request", StringComparison.OrdinalIgnoreCase) &&
103-
_source.Directory.Parent != null &&
104-
_source.Directory.Parent.Name.Equals("search", StringComparison.OrdinalIgnoreCase)
105+
_source.Directory.Parent != null &&
106+
_source.Directory.Parent.Name.Equals("search", StringComparison.OrdinalIgnoreCase)
105107
? 2
106108
: 3;
107109

@@ -153,9 +155,10 @@ public override void Visit(Container elements)
153155
continue;
154156
}
155157

156-
// if there is a section title since the last source block, don't add one
157-
var lastSourceBlock = _newDocument.LastOrDefault(e => e is Source);
158-
var lastSectionTitle = _newDocument.OfType<SectionTitle>().LastOrDefault(e => e.Level == _topSectionTitleLevel + 1);
158+
// if there is a section title since the last source block, don't add one
159+
var lastSourceBlock = _newDocument.LastOrDefault(e => e is Source);
160+
var lastSectionTitle =
161+
_newDocument.OfType<SectionTitle>().LastOrDefault(e => e.Level == _topSectionTitleLevel + 1);
159162
if (lastSourceBlock != null && lastSectionTitle != null)
160163
{
161164
var lastSectionTitleIndex = _newDocument.IndexOf(lastSectionTitle);
@@ -177,18 +180,19 @@ public override void Visit(Container elements)
177180
}
178181

179182
_newDocument.Add(source);
180-
break;
183+
break;
181184
case "initializer":
182-
case "queryinitializer":
183-
_newDocument.Add(CreateSubsectionTitle("Object Initializer syntax example"));
185+
case "queryinitializer":
186+
_newDocument.Add(CreateSubsectionTitle("Object Initializer syntax example"));
184187
_newDocument.Add(source);
185-
break;
188+
break;
186189
case "expectresponse":
187190
// Don't add the Handlng Response section title if it was the last title (it might be defined in the doc already)
188191
if (!LastSectionTitleMatches(text => text.Equals("Handling responses", StringComparison.OrdinalIgnoreCase)))
189192
{
190193
_newDocument.Add(CreateSubsectionTitle("Handling Responses"));
191194
}
195+
192196
_newDocument.Add(source);
193197
break;
194198
default:
@@ -231,7 +235,7 @@ public override void Visit(SectionTitle sectionTitle)
231235
var builder = new StringBuilder();
232236
using (var writer = new AsciiDocVisitor(new StringWriter(builder)))
233237
{
234-
writer.Visit((InlineContainer)sectionTitle);
238+
writer.Visit((InlineContainer) sectionTitle);
235239
}
236240

237241
var title = builder.ToString().PascalToHyphen();
@@ -253,86 +257,104 @@ public override void Visit(SectionTitle sectionTitle)
253257
base.Visit(sectionTitle);
254258
}
255259

256-
public override void Visit(AttributeEntry attributeEntry)
257-
{
258-
if (attributeEntry.Name != "xml-docs") return;
259-
260-
var value = attributeEntry.Value;
261-
262-
if (string.IsNullOrEmpty(value))
263-
{
264-
base.Visit(attributeEntry);
265-
return;
266-
}
267-
268-
var parts = value.Split(':');
269-
var assemblyName = parts[0];
270-
var typeName = parts[1];
271-
272-
string xmlDocsFile;
273-
Assembly assembly;
274-
string assemblyNamespace;
275-
276-
//TODO: tidy this up
277-
switch (assemblyName.ToLowerInvariant())
278-
{
279-
case "elasticsearch.net":
280-
xmlDocsFile = Path.GetFullPath(Path.Combine(Program.BuildOutputPath, "Elasticsearch.Net", "netstandard1.3", "Elasticsearch.Net.XML"));
281-
assembly = typeof(ElasticLowLevelClient).Assembly;
282-
assemblyNamespace = typeof(ElasticLowLevelClient).Namespace;
283-
break;
284-
default:
285-
xmlDocsFile = Path.GetFullPath(Path.Combine(Program.BuildOutputPath, "Nest", "netstandard1.3", "Nest.XML"));
286-
assembly = typeof(ElasticClient).Assembly;
287-
assemblyNamespace = typeof(ElasticClient).Namespace;
288-
break;
289-
}
290-
291-
// build xml documentation file on the fly if it doesn't exist
292-
if (!File.Exists(xmlDocsFile))
293-
{
294-
var project = _projects[assemblyName];
295-
296-
var compilation = project.GetCompilationAsync().Result;
297-
298-
using (var peStream = new MemoryStream())
299-
using (var commentStream = File.Create(xmlDocsFile))
300-
{
301-
var emitResult = compilation.Emit(peStream, null, commentStream);
302-
303-
if (!emitResult.Success)
304-
{
305-
var failures = emitResult.Diagnostics.Where(diagnostic =>
306-
diagnostic.IsWarningAsError ||
307-
diagnostic.Severity == DiagnosticSeverity.Error);
308-
309-
var builder = new StringBuilder($"Unable to emit compilation for: {assemblyName}");
310-
foreach (var diagnostic in failures)
311-
{
312-
builder.AppendLine($"{diagnostic.Id}: {diagnostic.GetMessage()}");
313-
}
314-
builder.AppendLine(new string('-', 30));
315-
316-
throw new Exception(builder.ToString());
317-
}
318-
}
319-
}
320-
321-
var assemblyMembers = DocReader.Read(assembly, xmlDocsFile);
322-
var type = assembly.GetType(assemblyNamespace + "." + typeName);
323-
var visitor = new XmlDocsVisitor(type);
324-
325-
visitor.VisitAssembly(assemblyMembers);
326-
if (visitor.LabeledListItems.Any())
327-
{
328-
var labeledList = new LabeledList();
329-
foreach (var item in visitor.LabeledListItems.OrderBy(l => l.Label))
330-
{
331-
labeledList.Items.Add(item);
332-
}
333-
_newDocument.Insert(_newDocument.IndexOf(attributeEntry), labeledList);
334-
}
335-
}
260+
public override void Visit(AttributeEntry attributeEntry)
261+
{
262+
if (attributeEntry.Name != "xml-docs") return;
263+
//true when running from the IDE, build/output might have not been created
264+
string configuration = null;
265+
if (Program.BuildOutputPath.Contains("src"))
266+
{
267+
//bin/Debug|Release/netcoreapp2.0
268+
configuration = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).Parent?.Name;
269+
return;
270+
}
271+
272+
string XmlFile(string project)
273+
{
274+
if (configuration == null)
275+
return Path.Combine(Program.BuildOutputPath, project, "netstandard1.3", $"{project}.XML");
276+
return Path.Combine(Program.BuildOutputPath, project, "bin", configuration, "netstandard1.3",
277+
$"{project}.XML");
278+
}
279+
280+
var value = attributeEntry.Value;
281+
282+
if (string.IsNullOrEmpty(value))
283+
{
284+
base.Visit(attributeEntry);
285+
return;
286+
}
287+
288+
var parts = value.Split(':');
289+
var assemblyName = parts[0];
290+
var typeName = parts[1];
291+
292+
string xmlDocsFile;
293+
Assembly assembly;
294+
string assemblyNamespace;
295+
296+
//TODO: tidy this up
297+
switch (assemblyName.ToLowerInvariant())
298+
{
299+
case "elasticsearch.net":
300+
xmlDocsFile = Path.GetFullPath(XmlFile("Elasticsearch.Net"));
301+
assembly = typeof(ElasticLowLevelClient).Assembly;
302+
assemblyNamespace = typeof(ElasticLowLevelClient).Namespace;
303+
break;
304+
default:
305+
xmlDocsFile = Path.GetFullPath(XmlFile("Nest"));
306+
assembly = typeof(ElasticClient).Assembly;
307+
assemblyNamespace = typeof(ElasticClient).Namespace;
308+
break;
309+
}
310+
311+
// build xml documentation file on the fly if it doesn't exist
312+
if (!File.Exists(xmlDocsFile))
313+
{
314+
var project = _projects[assemblyName];
315+
316+
var compilation = project.GetCompilationAsync().Result;
317+
318+
using (var peStream = new MemoryStream())
319+
using (var commentStream = File.Create(xmlDocsFile))
320+
{
321+
var emitResult = compilation.Emit(peStream, null, commentStream);
322+
323+
if (!emitResult.Success)
324+
{
325+
var failures = emitResult.Diagnostics.Where(diagnostic =>
326+
diagnostic.IsWarningAsError ||
327+
diagnostic.Severity == DiagnosticSeverity.Error);
328+
329+
var builder = new StringBuilder($"Unable to emit compilation for: {assemblyName}");
330+
foreach (var diagnostic in failures)
331+
{
332+
builder.AppendLine($"{diagnostic.Id}: {diagnostic.GetMessage()}");
333+
}
334+
335+
builder.AppendLine(new string('-', 30));
336+
337+
throw new Exception(builder.ToString());
338+
}
339+
}
340+
}
341+
342+
var assemblyMembers = DocReader.Read(assembly, xmlDocsFile);
343+
var type = assembly.GetType(assemblyNamespace + "." + typeName);
344+
var visitor = new XmlDocsVisitor(type);
345+
346+
visitor.VisitAssembly(assemblyMembers);
347+
if (visitor.LabeledListItems.Any())
348+
{
349+
var labeledList = new LabeledList();
350+
foreach (var item in visitor.LabeledListItems.OrderBy(l => l.Label))
351+
{
352+
labeledList.Items.Add(item);
353+
}
354+
355+
_newDocument.Insert(_newDocument.IndexOf(attributeEntry), labeledList);
356+
}
357+
}
336358

337359
private void RemoveDocDirectoryAttribute(Document document)
338360
{
@@ -351,7 +373,7 @@ private bool LastSectionTitleMatches(Func<string, bool> predicate)
351373
var builder = new StringBuilder();
352374
using (var visitor = new AsciiDocVisitor(new StringWriter(builder)))
353375
{
354-
visitor.Visit((InlineContainer)lastSectionTitle);
376+
visitor.Visit((InlineContainer) lastSectionTitle);
355377
}
356378

357379
return predicate(builder.ToString());
@@ -365,8 +387,8 @@ private SectionTitle CreateSubsectionTitle(string title)
365387
var level = _topSectionTitleLevel + 1;
366388
var sectionTitle = new SectionTitle(title, level);
367389

368-
// levels 1-3 need to be floating so the Elasticsearch docs generation does not
369-
// split into separate file
390+
// levels 1-3 need to be floating so the Elasticsearch docs generation does not
391+
// split into separate file
370392
if (level < 4)
371393
sectionTitle.IsFloating = true;
372394

src/CodeGeneration/DocGenerator/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ string P(string path)
1919

2020
InputDirPath = P(@"..\..\");
2121
OutputDirPath = P(@"..\..\..\docs");
22-
BuildOutputPath = P(@"..\..\..\build\output");
22+
BuildOutputPath = P(@"..\..\..\src");
2323
}
2424
else
2525
{

0 commit comments

Comments
 (0)