private static string MethodDefinitionSnippet(Mql5FunctionDefinition definition) { var builder = new StringBuilder(); builder.Append("```c\n"); var methodIntro = definition.MethodReturnType + " " + definition.MethodName + " ("; builder.Append(methodIntro); for (int i = 0; i < definition.Parameters.Count; i++) { if (i != 0) { builder.Append("," + "\n"); for (int j = 0; j < methodIntro.Length; j++) { builder.Append(" "); } } builder.Append(definition.Parameters[i].ParameterType + " " + definition.Parameters[i].ParameterName); } builder.Append(")\n"); builder.Append("```"); return(builder.ToString()); }
private static string GenerateFunctionDocumentationText(Mql5FunctionDefinition definition) { var mappedTypes = MapStringTypesToNetTypes(definition.Parameters); var methodInfo = dllExportsType.GetMethod(definition.MethodName, mappedTypes); // null if method was not found -> check if the newest version of the module was built in release mode var comments = reader.GetMethodComments(methodInfo); var builder = new StringBuilder(); if (comments.Summary == null) { throw new KeyNotFoundException(); } builder.Append(MethodHeader(definition) + "\n"); builder.Append(MethodDefinitionSnippet(definition) + "\n"); builder.Append(MethodSummery(comments.Summary) + "\n"); builder.Append("<dl>\n"); if (!string.IsNullOrWhiteSpace(comments.Returns)) { builder.Append("<dt>Returns</dt>\n"); builder.Append("<dd>\n"); builder.Append(MethodReturns(comments.Returns)); builder.Append("\n</dd>\n"); } if (!string.IsNullOrWhiteSpace(comments.Remarks)) { builder.Append("<dt>Remarks</dt>\n"); builder.Append("<dd>\n"); builder.Append(MethodRemarks(comments.Remarks)); builder.Append("\n</dd>\n"); } if (comments.Parameters.Count > 0) { builder.Append("<dt>Parameter</dt>\n"); builder.Append("<dd>\n"); builder.Append(MethodParameter(comments.Parameters, definition.Parameters)); builder.Append("\n</dd>\n"); } builder.Append("\n</dl>\n"); return(builder.ToString()); }
private static string MethodHeader(Mql5FunctionDefinition definition) { return($"## <a name=\"{definition.MethodName}\" /> {definition.MethodName}"); }
internal static List <Mql5FunctionDefinition> GetFunctionDefinitionBySourceFile(string filePath) { List <Mql5FunctionDefinition> definitions = new List <Mql5FunctionDefinition>(); var programText = File.ReadAllText(filePath); var programTree = CSharpSyntaxTree.ParseText(programText) .WithFilePath(filePath); var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location); var compilation = CSharpCompilation.Create( "MyCompilation", syntaxTrees: new[] { programTree }, new[] { mscorlib, }); var model = compilation.GetSemanticModel(programTree); var root = programTree.GetRoot(); var publicMethods = root.DescendantNodes() .OfType <MethodDeclarationSyntax>() .Where(method => method.Modifiers .Any(modifier => modifier.Kind() == SyntaxKind.PublicKeyword)); foreach (var methodDeclarationSyntax in publicMethods) { var definition = new Mql5FunctionDefinition(); foreach (var attributeListSyntax in methodDeclarationSyntax.AttributeLists) { foreach (var attributeSyntax in attributeListSyntax.Attributes) { var name = (IdentifierNameSyntax)attributeSyntax.Name; if (name.Identifier.Text == nameof(MqlFuncDocAttribute).Replace("Attribute", string.Empty)) { var methodSymbol = model.GetDeclaredSymbol(methodDeclarationSyntax); definition.ClassName = methodSymbol.ContainingType.Name; definition.MethodName = methodSymbol.Name; definition.MethodReturnType = methodSymbol.ReturnsVoid ? MapNetTypeToMqlType("void") : MapNetTypeToMqlType(methodSymbol.ReturnType.Name); foreach (var parameterSyntax in methodDeclarationSyntax.ParameterList.Parameters) { var parameterSymbol = model.GetDeclaredSymbol(parameterSyntax); var exampleValue = GetExampleValue(parameterSyntax); if (string.IsNullOrWhiteSpace(exampleValue)) { throw new ArgumentException($"{parameterSymbol.Name} in {methodSymbol.Name} has no documentation attribute assigned"); } string mappableType = string.Empty; if (parameterSymbol.Type is IArrayTypeSymbol) { var x = parameterSymbol.Type as IArrayTypeSymbol; mappableType = x.ElementType.Name + "[]"; } else { mappableType = parameterSymbol.Type.Name; } definition.Parameters.Add(new FunctionParameter() { ParameterName = parameterSymbol.Name, ParameterType = MapNetTypeToMqlType(mappableType), ParameterExample = exampleValue, }); } var xmlTrivia = methodDeclarationSyntax.GetLeadingTrivia() .Select(i => i.GetStructure()) .OfType <DocumentationCommentTriviaSyntax>() .FirstOrDefault(); definition.MethodXmlComments = xmlTrivia; } if (name.Identifier.Text == nameof(MqlFuncDocAttribute).Replace("Attribute", string.Empty)) { if (attributeSyntax.ArgumentList == null) { continue; } foreach (var argument in attributeSyntax.ArgumentList.Arguments) { if (argument.NameEquals.Name.Identifier.Text == nameof(MqlFuncDocAttribute.Order)) { var expression = argument.Expression as LiteralExpressionSyntax; definition.DocumentationOrder = int.TryParse(expression?.Token.ValueText, out var order) ? order : int.MaxValue; } if (argument.NameEquals.Name.Identifier.Text == nameof(MqlFuncDocAttribute.AdditionalCodeLines)) { var expression = argument.Expression as LiteralExpressionSyntax; definition.AdditionalCodeLines = expression?.Token.ValueText; } } } } } definitions.Add(definition); } return(definitions); }