Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.

Commit 2e853fe

Browse files
authored
Merge pull request #3 from microsoft/beheim/docComments
XML format for doc comments in C# code
2 parents 512e4d2 + 9cc8d0d commit 2e853fe

36 files changed

+1438
-303
lines changed

src/QsCompiler/CommandLineTool/Commands/Build.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ public static IEnumerable<Example> UsageExamples
5454

5555
// publicly accessible routines
5656

57+
/// <summary>
5758
/// Builds the compilation for the Q# code or Q# snippet and referenced assemblies defined by the given options.
5859
/// Invokes all specified targets (dotnet core apps) with suitable TargetOptions,
5960
/// that in particular specify the path to the compiled binary as input and the same output folder, verbosity, and suppressed warnings as the given options.
6061
/// The output folder is set to the current directory if one or more targets have been specified but the output folder was left unspecified.
6162
/// Returns a suitable error code if one of the compilation or generation steps fails.
6263
/// Throws an ArgumentNullException if any of the given arguments is null.
64+
/// </summary>
6365
public static int Run(BuildOptions options, ConsoleLogger logger)
6466
{
6567
if (options == null) throw new ArgumentNullException(nameof(options));

src/QsCompiler/CommandLineTool/Commands/Diagnose.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,12 @@ public static IEnumerable<Example> UsageExamples
5858
public bool PrintCompiledCode { get; set; }
5959
}
6060

61-
61+
/// <summary>
6262
/// Logs the content of each file in the given compilation as Information using the given logger.
6363
/// If the id of a file is consistent with the one assigned to a code snippet,
6464
/// strips the lines of code that correspond to the wrapping defined by WrapSnippet.
6565
/// Throws an ArgumentNullException if the given compilation is null.
66+
/// </summary>
6667
private static void PrintFileContentInMemory(Compilation compilation, ILogger logger)
6768
{
6869
if (compilation == null) throw new ArgumentNullException(nameof(compilation));
@@ -83,10 +84,12 @@ private static void PrintFileContentInMemory(Compilation compilation, ILogger lo
8384
}
8485
}
8586

87+
/// <summary>
8688
/// Logs the tokenization of each file in the given compilation as Information using the given logger.
8789
/// If the id of a file is consistent with the one assigned to a code snippet,
8890
/// strips the tokens that correspond to the wrapping defined by WrapSnippet.
8991
/// Throws an ArgumentNullException if the given compilation is null.
92+
/// </summary>
9093
private static void PrintContentTokenization(Compilation compilation, ILogger logger)
9194
{
9295
if (compilation == null) throw new ArgumentNullException(nameof(compilation));
@@ -113,13 +116,15 @@ private static void PrintContentTokenization(Compilation compilation, ILogger lo
113116
}
114117
}
115118

119+
/// <summary>
116120
/// Logs the part of the given evaluated syntax tree that corresponds to each file
117121
/// in the given compilation as Information using the given logger.
118122
/// If the given evaluated tree is null, queries the tree contained in the given compilation instead.
119123
/// If the id of a file is consistent with the one assigned to a code snippet,
120124
/// strips the lines of code that correspond to the wrapping defined by WrapSnippet.
121125
/// Throws an ArgumentException if this is not possible because the given syntax tree is inconsistent with that wrapping.
122126
/// Throws an ArgumentNullException if the given compilation is null.
127+
/// </summary>
123128
private static void PrintSyntaxTree(IEnumerable<QsNamespace> evaluatedTree, Compilation compilation, ILogger logger)
124129
{
125130
if (compilation == null) throw new ArgumentNullException(nameof(compilation));
@@ -141,13 +146,15 @@ void PrintTree(string serialization) => logger.Log(
141146
}
142147
}
143148

149+
/// <summary>
144150
/// Logs the generated Q# code for the part of the given evaluated syntax tree that corresponds to each file
145151
/// in the given compilation as Information using the given logger.
146152
/// If the given evaluated tree is null, queries the tree contained in the given compilation instead.
147153
/// If the id of a file is consistent with the one assigned to a code snippet,
148154
/// strips the lines of code that correspond to the wrapping defined by WrapSnippet.
149155
/// Throws an ArgumentException if this is not possible because the given syntax tree is inconsistent with that wrapping.
150156
/// Throws an ArgumentNullException if the given compilation is null.
157+
/// </summary>
151158
private static void PrintGeneratedQs(IEnumerable<QsNamespace> evaluatedTree, Compilation compilation, ILogger logger)
152159
{
153160
if (compilation == null) throw new ArgumentNullException(nameof(compilation));
@@ -174,9 +181,11 @@ private static void PrintGeneratedQs(IEnumerable<QsNamespace> evaluatedTree, Com
174181

175182
// publicly accessible methods
176183

184+
/// <summary>
177185
/// Strips the namespace and callable declaration that is consistent with the wrapping defined by WrapSnippet.
178186
/// Throws an ArgumentException if this is not possible because the given syntax tree is inconsistent with that wrapping.
179187
/// Throws an ArgumentNullException if the given syntaxTree is null.
188+
/// </summary>
180189
public static IEnumerable<QsStatement> StripSnippetWrapping(IEnumerable<QsNamespace> syntaxTree)
181190
{
182191
if (syntaxTree == null) throw new ArgumentNullException(nameof(syntaxTree));
@@ -189,10 +198,12 @@ public static IEnumerable<QsStatement> StripSnippetWrapping(IEnumerable<QsNamesp
189198
else throw incorrectWrapperException;
190199
}
191200

201+
/// <summary>
192202
/// Builds the compilation for the Q# code or Q# snippet and referenced assemblies defined by the given options.
193203
/// Prints the data structures requested by the given options using the given logger.
194204
/// Returns a suitable error code if one of the compilation or generation steps fails.
195205
/// Throws an ArgumentNullException if any of the given arguments is null.
206+
/// </summary>
196207
public static int Run(DiagnoseOptions options, ConsoleLogger logger)
197208
{
198209
if (options == null) throw new ArgumentNullException(nameof(options));

src/QsCompiler/CommandLineTool/Commands/Format.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,26 @@ public static IEnumerable<Example> UsageExamples
4444
public string OutputFolder { get; set; }
4545
}
4646

47-
47+
/// <summary>
4848
/// Regex that matches anything within array brackets.
49+
/// </summary>
4950
public static readonly Regex WithinArrayBrackets =
5051
new Regex(@"\[(?:[^\[\]]|(?<ctr>\[)|(?<-ctr>\]))*(?(ctr)(?!))\]");
5152

53+
/// <summary>
5254
/// Replaces all semicolons that occur within array brackets in the given string with commas.
55+
/// </summary>
5356
public static string UpdateArrayLiterals(string fileContent)
5457
{
5558
string ReplaceSemicolons(Match match) => match.Value.Replace(';', ',');
5659
return WithinArrayBrackets.Replace(fileContent, ReplaceSemicolons);
5760
}
5861

5962

63+
/// <summary>
6064
/// Returns formatted Q# code for the given statement.
6165
/// Throws an ArgumentNullException if the given statement is null.
66+
/// </summary>
6267
internal static string FormatStatement(QsStatement statement)
6368
{
6469
if (statement == null) throw new ArgumentNullException(nameof(statement));
@@ -67,11 +72,13 @@ internal static string FormatStatement(QsStatement statement)
6772
return ToCode.Output;
6873
}
6974

75+
/// <summary>
7076
/// Generates formatted Q# code based on the part of the syntax tree that corresponds to each file in the given compilation.
7177
/// If the id of a file is consistent with the one assigned to a code snippet,
7278
/// strips the lines of code that correspond to the wrapping defined by WrapSnippet.
7379
/// Throws an ArgumentException if this is not possible because the given syntax tree is inconsistent with that wrapping.
7480
/// Throws an ArgumentNullException if the given compilation is null.
81+
/// </summary>
7582
private static IEnumerable<string> GenerateQsCode(Compilation compilation, NonNullable<string> file, ILogger logger)
7683
{
7784
if (compilation == null) throw new ArgumentNullException(nameof(compilation));
@@ -105,12 +112,14 @@ string FormatComments(IEnumerable<string> comments) =>
105112
};
106113
}
107114

115+
/// <summary>
108116
/// Generates formatted Q# code for the file with the given uri based on the syntax tree in the given compilation.
109117
/// If the id of the file is consistent with the one assigned to a code snippet,
110118
/// logs the generated code using the given logger.
111119
/// Creates a file containing the generated code in the given output folder otherwise.
112120
/// Returns true if the generation succeeded, and false if an exception was thrown.
113121
/// Throws an ArgumentNullException if the given compilation, the file uri or its absolute path are null.
122+
/// </summary>
114123
private static bool GenerateFormattedQsFile(Compilation compilation, NonNullable<string> fileName, string outputFolder, ILogger logger)
115124
{
116125
if (compilation == null) throw new ArgumentNullException(nameof(compilation));
@@ -137,11 +146,13 @@ private static bool GenerateFormattedQsFile(Compilation compilation, NonNullable
137146
return true;
138147
}
139148

149+
/// <summary>
140150
/// Builds the compilation for the Q# code or Q# snippet and referenced assemblies defined by the given options.
141151
/// Generates formatted Q# code for each source file in the compilation.
142152
/// Returns a suitable error code if some of the source files or references could not be found or loaded, or if the Q# generation failed.
143153
/// Compilation errors are not reflected in the return code, but are logged using the given logger.
144154
/// Throws an ArgumentNullException if any of the given arguments is null.
155+
/// </summary>
145156
public static int Run(FormatOptions options, ConsoleLogger logger)
146157
{
147158
if (options == null) throw new ArgumentNullException(nameof(options));

src/QsCompiler/CommandLineTool/CompilerOptions.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ public enum LogFormat
6060

6161
// routines related to logging
6262

63+
/// <summary>
6364
/// If a logger is given, logs the options as CommandLineArguments Information before returning the printed string.
65+
/// </summary>
6466
public string[] Print(ILogger logger = null)
6567
{
6668
string value(PropertyInfo p)
@@ -77,7 +79,9 @@ string value(PropertyInfo p)
7779
return msg;
7880
}
7981

82+
/// <summary>
8083
/// Given a LogFormat, returns a suitable routing for formatting diagnostics.
84+
/// </summary>
8185
internal static Func<Diagnostic, string> LoggingFormat(LogFormat format)
8286
{
8387
switch (format)
@@ -88,8 +92,10 @@ internal static Func<Diagnostic, string> LoggingFormat(LogFormat format)
8892
}
8993
}
9094

95+
/// <summary>
9196
/// Creates a suitable logger for the given command line options,
9297
/// logging the given arguments if the verbosity is high enough.
98+
/// </summary>
9399
public ConsoleLogger GetLogger(DiagnosticSeverity minimumVerbosity = DiagnosticSeverity.Warning)
94100
{
95101
var logger = new ConsoleLogger(
@@ -104,7 +110,9 @@ public ConsoleLogger GetLogger(DiagnosticSeverity minimumVerbosity = DiagnosticS
104110

105111
// routines related to processing snippets
106112

113+
/// <summary>
107114
/// text document identifier used to identify the code snippet in diagnostic mode
115+
/// </summary>
108116
private static readonly Uri SNIPPET_FILE_URI = new Uri(Path.GetFullPath("__CODE_SNIPPET__.qs"));
109117
private static NonNullable<string> SNIPPET_FILE_ID
110118
{
@@ -117,29 +125,39 @@ private static NonNullable<string> SNIPPET_FILE_ID
117125
}
118126
}
119127

128+
/// <summary>
120129
/// name of the namespace within which code snippets are compiled
130+
/// </summary>
121131
private const string SNIPPET_NAMESPACE = "_CODE_SNIPPET_NS_";
132+
/// <summary>
122133
/// name of the callable within which code snippets are compiled
134+
/// </summary>
123135
private const string SNIPPET_CALLABLE = "_CODE_SNIPPET_CALLABLE_";
124136

137+
/// <summary>
125138
/// wraps the given content into a namespace and callable that maps Unit to Unit
139+
/// </summary>
126140
public static string AsSnippet(string content, bool inFunction = false) =>
127141
$"{Declarations.Namespace} {SNIPPET_NAMESPACE} {{ \n " +
128142
$"{(inFunction ? Declarations.Function : Declarations.Operation)} {SNIPPET_CALLABLE} () : {Types.Unit} {{ \n" +
129143
$"{content} \n" + // no indentation such that position info is accurate
130144
$"}} \n" +
131145
$"}}";
132146

147+
/// <summary>
133148
/// helper function that returns true if the given file id is the one a compilation unit manager would assign to the code snipped
149+
/// </summary>
134150
public static bool IsCodeSnippet(NonNullable<string> fileId) =>
135151
fileId.Value == SNIPPET_FILE_ID.Value;
136152

137153

154+
/// <summary>
138155
/// Returns a function that given a routine for loading files from disk,
139156
/// return an enumerable with all text document identifiers and the corresponding file content
140157
/// for the source code or Q# snippet specified by the given options.
141158
/// If both the Input and the CodeSnippet property are set, or none of these properties is set in the given options,
142159
/// logs a suitable error and returns and empty dictionary.
160+
/// </summary>
143161
internal CompilationLoader.SourceLoader LoadSourcesOrSnippet (ILogger logger) => loadFromDisk =>
144162
{
145163
bool inputIsEmptyOrNull = this.Input == null || !this.Input.Any();

src/QsCompiler/CommandLineTool/Logging.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ public ConsoleLogger(
2323
DiagnosticSeverity verbosity = DiagnosticSeverity.Warning,
2424
IEnumerable<int> noWarn = null, int lineNrOffset = 0)
2525
: base(verbosity, noWarn, lineNrOffset) =>
26-
this.ApplyFormatting = format ?? Formatting.HumanReadableFormat;
26+
this.ApplyFormatting = format ?? Formatting.HumanReadableFormat;
2727

28+
/// <summary>
2829
/// Prints the given message to the Console.
2930
/// Errors and Warnings are printed to the error stream.
3031
/// Throws an ArgumentNullException if the given message is null.
32+
/// </summary>
3133
private static void PrintToConsole(DiagnosticSeverity severity, string message)
3234
{
3335
if (message == null) throw new ArgumentNullException(nameof(message));
@@ -46,8 +48,10 @@ private static void PrintToConsole(DiagnosticSeverity severity, string message)
4648
finally { Console.ForegroundColor = consoleColor; }
4749
}
4850

51+
/// <summary>
4952
/// Prints a summary containing the currently counted number of errors, warnings and exceptions.
5053
/// Indicates a compilation failure if the given status does not correspond to the ReturnCode indicating a success.
54+
/// </summary>
5155
public virtual void ReportSummary(int status = CommandLineCompiler.ReturnCode.SUCCESS)
5256
{
5357
string ItemString(int nr, string name) => $"{nr} {name}{(nr == 1 ? "" : "s")}";

src/QsCompiler/CommandLineTool/TargetOptions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
namespace Microsoft.Quantum.QsCompiler.CommandLineCompiler
99
{
10+
/// <summary>
1011
/// command line options for Q# build targets
12+
/// </summary>
1113
public class TargetOptions
1214
{
1315
[Option('v', "verbose", Required = false, Default = false,

src/QsCompiler/CompilationManager/AttributeReader.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,20 @@
1313

1414
namespace Microsoft.Quantum.QsCompiler
1515
{
16+
/// <summary>
1617
/// This class relies on the ECMA-335 standard to extract information contained in compiled binaries.
1718
/// The standard can be found here: https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf,
1819
/// and the section on custom attributes starts on page 267.
20+
/// </summary>
1921
public static class AttributeReader
2022
{
23+
/// <summary>
2124
/// There are two possible handle kinds in use for the constructor of a custom attribute,
2225
/// one pointing to the MethodDef table and one to the MemberRef table, see p.216 in the ECMA standard linked above and
2326
/// https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/CustomAttribute.cs#L42
2427
/// This routine extracts the namespace and type name of the given attribute and returns the corresponding string handles.
2528
/// Returns null if the constructor handle is not a MethodDefinition or a MemberDefinition.
29+
/// </summary>
2630
private static (StringHandle, StringHandle)? GetAttributeType(MetadataReader metadataReader, CustomAttribute attribute)
2731
{
2832
if (attribute.Constructor.Kind == HandleKind.MethodDefinition)
@@ -64,11 +68,13 @@ private static (string, string)? GetAttribute(MetadataReader metadataReader, Cus
6468
return null;
6569
}
6670

71+
/// <summary>
6772
/// Given a stream with the bytes of an assembly, read its custom attributes and
6873
/// returns a tuple containing the name of the attribute and the constructor argument
6974
/// for all attributes defined in a Microsoft.Quantum* namespace.
7075
/// Throws an ArgumentNullException if the given stream is null.
7176
/// Throws the corresponding exceptions if the information cannot be extracted.
77+
/// </summary>
7278
public static IEnumerable<(string, string)> GetQsCompilerAttributes(Stream stream)
7379
{
7480
if (stream == null) throw new ArgumentNullException(nameof(stream));
@@ -83,12 +89,14 @@ private static (string, string)? GetAttribute(MetadataReader metadataReader, Cus
8389
}
8490
}
8591

92+
/// <summary>
8693
/// Given the full name of an assembly, opens the file and reads its custom attributes and
8794
/// returns a tuple containing the name of the attribute and the constructor argument
8895
/// for all attributes defined in the Microsoft.Quantum* namespace.
8996
/// Throws an ArgumentNullException if the given uri is null.
9097
/// Throws a FileNotFoundException if no file with the given name exists.
9198
/// Throws the corresponding exceptions if the information cannot be extracted.
99+
/// </summary>
92100
public static IEnumerable<(string, string)> GetQsCompilerAttributes(Uri asm)
93101
{
94102
if (asm == null) throw new ArgumentNullException(nameof(asm));

0 commit comments

Comments
 (0)