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}");
 }
Exemple #4
0
        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);
        }