예제 #1
0
        /// <summary>
        /// Generates schema for the provided list of types and store them in the provided dictionary.
        /// </summary>
        /// <param name="allListedTypes">The listed types to fetch schema for.</param>
        /// <param name="crefSchemaMap">The cref to <see cref="InternalSchemaGenerationInfo"/> map.</param>
        /// <param name="typeFetcher">The type fetcher used to fetch type information using reflection.</param>
        /// <param name="schemaReferenceRegistry"><see cref="SchemaReferenceRegistry"/>.</param>
        private void BuildCrefSchemaMap(
            IList <string> allListedTypes,
            Dictionary <string, InternalSchemaGenerationInfo> crefSchemaMap,
            TypeFetcher typeFetcher,
            SchemaReferenceRegistry schemaReferenceRegistry)
        {
            var key = allListedTypes.ToCrefKey();

            var schemaInfo = new InternalSchemaGenerationInfo();

            try
            {
                var type   = typeFetcher.LoadTypeFromCrefValues(allListedTypes);
                var schema = schemaReferenceRegistry.FindOrAddReference(type);
                schemaInfo.Schema = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
            }
            catch (Exception e)
            {
                var error = new GenerationError
                {
                    ExceptionType = e.GetType().Name,
                    Message       = e.Message
                };

                schemaInfo.Error = error;
            }

            if (!crefSchemaMap.ContainsKey(key))
            {
                crefSchemaMap.Add(key, schemaInfo);
            }
        }
예제 #2
0
        public void TypeFetcherShouldReturnCorrectTypeData(
            string testCaseName,
            IList <string> inputBinaryFiles,
            IList <string> crefValues,
            string expectedTypeAsString)
        {
            _output.WriteLine(testCaseName);

            var typeFetcher = new TypeFetcher(inputBinaryFiles);
            var type        = typeFetcher.LoadTypeFromCrefValues(crefValues);

            type.ToString().Should().Be(expectedTypeAsString);
        }
예제 #3
0
        /// <summary>
        /// Provided a field cref value, fetches the field value using reflection.
        /// </summary>
        /// <param name="crefValue">The cref value for the field.</param>
        /// <param name="crefFieldMap">The cref value to <see cref="FieldValueInfo"/> map.</param>
        /// <param name="typeFetcher">The type fetcher used to fetch field value from the loaded assemblies.</param>
        private void BuildCrefFieldValueMap(
            string crefValue,
            Dictionary <string, FieldValueInfo> crefFieldMap,
            TypeFetcher typeFetcher)
        {
            if (string.IsNullOrWhiteSpace(crefValue) || crefFieldMap.ContainsKey(crefValue))
            {
                return;
            }

            var fieldValueInfo = new FieldValueInfo();

            try
            {
                var typeName = crefValue.ExtractTypeNameFromFieldCref();
                var type     = typeFetcher.LoadTypeFromCrefValues(new List <string> {
                    typeName
                });
                var fieldName = crefValue.ExtractFieldNameFromCref();

                var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
                var field  = fields.FirstOrDefault(f => f.Name == fieldName);

                if (field == null)
                {
                    var errorMessage = string.Format(
                        SpecificationGenerationMessages.FieldNotFound,
                        fieldName,
                        typeName);

                    throw new TypeLoadException(errorMessage);
                }

                fieldValueInfo.Value = field.GetValue(null).ToString();
            }
            catch (Exception e)
            {
                var error = new GenerationError
                {
                    ExceptionType = e.GetType().Name,
                    Message       = e.Message
                };

                fieldValueInfo.Error = error;
            }

            crefFieldMap.Add(crefValue, fieldValueInfo);
        }
예제 #4
0
        /// <summary>
        /// Processes the "header" tag child elements of the provide XElement
        /// and generates a map of string to OpenApiHeader.
        /// </summary>
        /// <param name="xElement">The XElement to process.</param>
        /// <param name="typeFetcher">The type fetcher.</param>
        /// <param name="schemaReferenceRegistry">The schema reference registry.</param>
        /// <returns>The map of string to OpenApiHeader.</returns>
        internal static Dictionary <string, OpenApiHeader> ToOpenApiHeaders(
            this XElement xElement,
            TypeFetcher typeFetcher,
            SchemaReferenceRegistry schemaReferenceRegistry)
        {
            var headerElements = xElement.Elements()
                                 .Where(
                p => p.Name == KnownXmlStrings.Header)
                                 .ToList();

            var openApiHeaders = new Dictionary <string, OpenApiHeader>();

            foreach (var headerElement in headerElements)
            {
                var name = headerElement.Attribute(KnownXmlStrings.Name)?.Value.Trim();
                if (string.IsNullOrWhiteSpace(name))
                {
                    throw new InvalidHeaderException(
                              string.Format(SpecificationGenerationMessages.UndocumentedName, "header"));
                }

                var description = headerElement
                                  .Elements()
                                  .FirstOrDefault(p => p.Name == KnownXmlStrings.Description)?.Value.Trim().RemoveBlankLines();

                var listedTypes = headerElement.GetListedTypes();
                var type        = typeFetcher.LoadTypeFromCrefValues(listedTypes);

                var schema = schemaReferenceRegistry.FindOrAddReference(type);
                openApiHeaders.Add(
                    name,
                    new OpenApiHeader
                {
                    Description = description,
                    Schema      = schema
                });
            }

            return(openApiHeaders);
        }
예제 #5
0
        /// <summary>
        /// Processes the "example" tag child elements of the provide XElement
        /// and generates a map of string to OpenApiExample.
        /// </summary>
        /// <param name="xElement">The XElement to process.</param>
        /// <param name="typeFetcher">The type fetcher.</param>
        /// <returns>The map of string to OpenApiExample.</returns>
        internal static Dictionary <string, OpenApiExample> ToOpenApiExamples(
            this XElement xElement,
            TypeFetcher typeFetcher)
        {
            var exampleElements = xElement.Elements().Where(p => p.Name == KnownXmlStrings.Example);
            var examples        = new Dictionary <string, OpenApiExample>();
            var exampleCounter  = 1;

            foreach (var exampleElement in exampleElements)
            {
                var exampleName = exampleElement.Attribute(KnownXmlStrings.Name)?.Value.Trim();
                var example     = exampleElement.ToOpenApiExample(typeFetcher);

                if (example != null)
                {
                    examples.Add(
                        string.IsNullOrWhiteSpace(exampleName) ? $"example{exampleCounter++}" : exampleName,
                        example);
                }
            }

            return(examples);
        }
 public OpenWithMenu(TypeFetcher type_fetcher, params string [] ignore_apps)
 {
     this.type_fetcher = type_fetcher;
     this.ignore_apps = new List<string> (ignore_apps);
 }
 public OpenWithMenu(TypeFetcher type_fetcher)
     : this(type_fetcher, null)
 {
 }
예제 #8
0
        /// <summary>
        /// Fetches all the cref's from the provided operation element and build cref --> schema, cref --> field value
        /// maps.
        /// </summary>
        /// <param name="currentXElement">The XElement to fetch cref and see tags for.</param>
        /// <param name="crefSchemaMap">The cref to <see cref="InternalSchemaGenerationInfo"/> map.</param>
        /// <param name="crefFieldMap">The cref to <see cref="FieldValueInfo"/> map.</param>
        /// <param name="typeFetcher">The type fetcher used to fetch type, field information.</param>
        /// <param name="schemaReferenceRegistry"><see cref="SchemaReferenceRegistry"/>.</param>
        private void BuildMap(
            XElement currentXElement,
            Dictionary <string, InternalSchemaGenerationInfo> crefSchemaMap,
            Dictionary <string, FieldValueInfo> crefFieldMap,
            TypeFetcher typeFetcher,
            SchemaReferenceRegistry schemaReferenceRegistry)
        {
            if (currentXElement == null)
            {
                return;
            }

            var cref = currentXElement.Attribute(KnownXmlStrings.Cref)?.Value.Trim();

            if (!string.IsNullOrWhiteSpace(cref))
            {
                var allListedTypes = new List <string>()
                {
                    cref
                };

                if (allListedTypes.Where(i => i.StartsWith("F:")).Any())
                {
                    BuildCrefFieldValueMap(allListedTypes.FirstOrDefault(), crefFieldMap, typeFetcher);
                }
                else
                {
                    BuildCrefSchemaMap(allListedTypes, crefSchemaMap, typeFetcher, schemaReferenceRegistry);
                }
            }

            if (!currentXElement.Elements().Any())
            {
                return;
            }

            var seeNodes = currentXElement.Elements().Where(i => i.Name == KnownXmlStrings.See);

            if (seeNodes.Any())
            {
                var allListedTypes = seeNodes
                                     .Select(node => node.Attribute(KnownXmlStrings.Cref)?.Value)
                                     .Where(crefValue => crefValue != null).ToList();

                if (allListedTypes.Where(i => i.StartsWith("F:")).Any())
                {
                    BuildCrefFieldValueMap(allListedTypes.FirstOrDefault(), crefFieldMap, typeFetcher);
                }
                else
                {
                    BuildCrefSchemaMap(allListedTypes, crefSchemaMap, typeFetcher, schemaReferenceRegistry);
                }
            }

            var remainingNodes = currentXElement.Elements().Where(i => i.Name != KnownXmlStrings.See);

            foreach (var remainingNode in remainingNodes)
            {
                BuildMap(
                    remainingNode,
                    crefSchemaMap,
                    crefFieldMap,
                    typeFetcher,
                    schemaReferenceRegistry);
            }
        }
예제 #9
0
        /// <summary>
        /// Builds <see cref="InternalGenerationContext"/> by reflecting into contract assemblies.
        /// </summary>
        /// <param name="contractAssembliesPaths">The contract assemlby paths.</param>
        /// <param name="operationElements">The operation xelements.</param>
        /// <param name="propertyElements">The property xelements</param>
        /// <param name="documentVariantElementName">The document variant element name.</param>
        /// <param name="internalSchemaGenerationSettings"><see cref="InternalSchemaGenerationSettings"/></param>
        /// <returns>Serialized <see cref="InternalGenerationContext"/></returns>
        public string BuildInternalGenerationContext(
            IList <string> contractAssembliesPaths,
            IList <string> operationElements,
            IList <string> propertyElements,
            string documentVariantElementName,
            InternalSchemaGenerationSettings internalSchemaGenerationSettings)
        {
            var crefSchemaMap = new Dictionary <string, InternalSchemaGenerationInfo>();

            List <XElement> xPropertyElements = propertyElements.Select(XElement.Parse).ToList();

            var propertyMap = new Dictionary <string, string>();

            foreach (var xPropertyElement in xPropertyElements)
            {
                var name = xPropertyElement
                           .Attributes(KnownXmlStrings.Name)?.FirstOrDefault()?.Value?.Split(':')[1];
                var description = xPropertyElement.Element(KnownXmlStrings.Summary)?.Value.RemoveBlankLines();

                if (!propertyMap.ContainsKey(name))
                {
                    propertyMap.Add(name, description);
                }
            }

            var referenceRegistryMap = new Dictionary <DocumentVariantInfo, SchemaReferenceRegistry>();

            var schemaGenerationSettings = new SchemaGenerationSettings(new DefaultPropertyNameResolver());

            if (internalSchemaGenerationSettings.PropertyNameResolverName ==
                typeof(CamelCasePropertyNameResolver).FullName)
            {
                schemaGenerationSettings = new SchemaGenerationSettings(new CamelCasePropertyNameResolver());
            }

            var internalGenerationContext = new InternalGenerationContext();

#if !NETFRAMEWORK
            var typeFetcher = new TypeFetcher(contractAssembliesPaths, Context);
#else
            var typeFetcher = new TypeFetcher(contractAssembliesPaths);
#endif

            List <XElement> xOperationElements = operationElements.Select(XElement.Parse).ToList();

            foreach (var xOperationElement in xOperationElements)
            {
                if (!referenceRegistryMap.ContainsKey(DocumentVariantInfo.Default))
                {
                    referenceRegistryMap.Add(
                        DocumentVariantInfo.Default,
                        new SchemaReferenceRegistry(schemaGenerationSettings, propertyMap));
                }

                // Recursively build the various cref-schema, cref-fieldValue map.
                BuildMap(
                    xOperationElement,
                    crefSchemaMap,
                    internalGenerationContext.CrefToFieldValueMap,
                    typeFetcher,
                    referenceRegistryMap[DocumentVariantInfo.Default]);

                var customElements = xOperationElement.Descendants(documentVariantElementName);

                // Build the various cref-schema, cref-fieldValue map for each customElement.
                foreach (var customElement in customElements)
                {
                    var documentVariantInfo = new DocumentVariantInfo
                    {
                        Categorizer = customElement.Name.LocalName.Trim(),
                        Title       = customElement.Value.Trim()
                    };

                    if (!referenceRegistryMap.ContainsKey(documentVariantInfo))
                    {
                        referenceRegistryMap.Add(
                            documentVariantInfo,
                            new SchemaReferenceRegistry(schemaGenerationSettings, propertyMap));
                    }

                    BuildMap(
                        xOperationElement,
                        crefSchemaMap,
                        internalGenerationContext.CrefToFieldValueMap,
                        typeFetcher,
                        referenceRegistryMap[documentVariantInfo]);
                }
            }

            foreach (var key in referenceRegistryMap.Keys)
            {
                var references = referenceRegistryMap[key].References;

                internalGenerationContext.VariantSchemaReferenceMap.Add(
                    key.ToString(),
                    references.ToDictionary(k => k.Key, k => k.Value.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0)));
            }

            internalGenerationContext.CrefToSchemaMap = crefSchemaMap;

            // Serialize the context to transfer across app domain.
            var document = JsonConvert.SerializeObject(internalGenerationContext);

            return(document);
        }
예제 #10
0
        private static OpenApiExample ToOpenApiExample(this XElement element, TypeFetcher typeFetcher)
        {
            var exampleChildElements = element.Elements();

            if (!exampleChildElements.Any())
            {
                return(null);
            }

            var summaryElement = exampleChildElements.FirstOrDefault(p => p.Name == KnownXmlStrings.Summary);

            var openApiExample = new OpenApiExample();

            if (summaryElement != null)
            {
                openApiExample.Summary = summaryElement.Value;
            }

            var valueElement = exampleChildElements.FirstOrDefault(p => p.Name == KnownXmlStrings.Value);
            var urlElement   = exampleChildElements.FirstOrDefault(p => p.Name == KnownXmlStrings.Url);

            if (valueElement != null && urlElement != null)
            {
                throw new InvalidExampleException(SpecificationGenerationMessages.ProvideEitherValueOrUrlTag);
            }

            IOpenApiAny exampleValue = null;

            if (valueElement != null)
            {
                var seeNodes  = element.Descendants(KnownXmlStrings.See);
                var crefValue = seeNodes
                                .Select(node => node.Attribute(KnownXmlStrings.Cref)?.Value)
                                .FirstOrDefault(crefVal => crefVal != null);

                if (string.IsNullOrWhiteSpace(valueElement.Value) && string.IsNullOrWhiteSpace(crefValue))
                {
                    throw new InvalidExampleException(SpecificationGenerationMessages.ProvideValueForExample);
                }

                if (!string.IsNullOrWhiteSpace(crefValue))
                {
                    var typeName = crefValue.ExtractTypeNameFromFieldCref();
                    var type     = typeFetcher.LoadTypeFromCrefValues(new List <string> {
                        typeName
                    });
                    var fieldName = crefValue.ExtractFieldNameFromCref();

                    var fields = type.GetFields(BindingFlags.Public
                                                | BindingFlags.Static);
                    var field = fields.FirstOrDefault(f => f.Name == fieldName);

                    if (field == null)
                    {
                        var errorMessage = string.Format(
                            SpecificationGenerationMessages.FieldNotFound,
                            fieldName,
                            typeName);

                        throw new TypeLoadException(errorMessage);
                    }

                    exampleValue = new OpenApiStringReader().ReadFragment <IOpenApiAny>(
                        field.GetValue(null).ToString(),
                        OpenApiSpecVersion.OpenApi3_0,
                        out OpenApiDiagnostic _);
                }

                if (!string.IsNullOrWhiteSpace(valueElement.Value))
                {
                    exampleValue = new OpenApiStringReader()
                                   .ReadFragment <IOpenApiAny>(
                        valueElement.Value,
                        OpenApiSpecVersion.OpenApi3_0,
                        out OpenApiDiagnostic _);
                }

                openApiExample.Value = exampleValue;
            }

            if (urlElement != null)
            {
                openApiExample.ExternalValue = urlElement.Value;
            }

            return(openApiExample);
        }
예제 #11
0
 public OpenWithComboBox(TypeFetcher type_fetcher, params string [] ignore_apps)
 {
     this.type_fetcher = type_fetcher;
     this.ignore_apps  = new List <string> (ignore_apps);
 }
예제 #12
0
 public OpenWithComboBox(TypeFetcher type_fetcher) : this(type_fetcher, null)
 {
 }
예제 #13
0
 public OpenWithMenu(TypeFetcher type_fetcher) : this(type_fetcher, null)
 {
 }
예제 #14
0
 public OpenWithComboBox(TypeFetcher type_fetcher)
     : this(type_fetcher, null)
 {
 }