in src/Microsoft.OpenApi.CSharpAnnotations.DocumentGeneration/InternalOpenApiGenerator.cs [210:454]
public IDictionary<DocumentVariantInfo, OpenApiDocument> GenerateOpenApiDocuments(
IList<XDocument> annotationXmlDocuments,
IList<string> contractAssemblyPaths,
string configurationXml,
string openApiDocumentVersion,
string openApiInfoDescription,
out GenerationDiagnostic generationDiagnostic)
{
IDictionary<DocumentVariantInfo, OpenApiDocument> openApiDocuments
= new Dictionary<DocumentVariantInfo, OpenApiDocument>();
var operationElements = new List<XElement>();
var propertyElements = new List<XElement>();
foreach (var annotationXmlDocument in annotationXmlDocuments)
{
operationElements.AddRange(
annotationXmlDocument.XPathSelectElements("//doc/members/member[url and verb]"));
propertyElements.AddRange(annotationXmlDocument.XPathSelectElements("//doc/members/member")
.Where(
m => m.Attribute(KnownXmlStrings.Name) != null &&
m.Attribute(KnownXmlStrings.Name).Value.StartsWith("P:")));
}
XElement operationConfigElement = null;
XElement documentConfigElement = null;
var documentVariantElementNames = new List<string>();
if (!string.IsNullOrWhiteSpace(configurationXml))
{
var configurationXmlDocument = XDocument.Parse(configurationXml);
operationConfigElement = configurationXmlDocument.XPathSelectElement("//configuration/operation");
documentConfigElement = configurationXmlDocument.XPathSelectElement("//configuration/document");
documentVariantElementNames = configurationXmlDocument
.XPathSelectElements("//configuration/document/variant/name")
.Select(variantName => variantName.Value)
.ToList();
}
if (!operationElements.Any())
{
generationDiagnostic = new GenerationDiagnostic
{
DocumentGenerationDiagnostic = new DocumentGenerationDiagnostic
{
Errors =
{
new GenerationError
{
Message = SpecificationGenerationMessages.NoOperationElementFoundToParse
}
}
}
};
return openApiDocuments;
}
try
{
var propertyNameResolverTypeName = _openApiDocumentGenerationSettings.SchemaGenerationSettings
.PropertyNameResolver.GetType().FullName;
var internalGenerationContext = new InternalGenerationContext();
var internalSchemaGenerationSettings = new InternalSchemaGenerationSettings()
{
PropertyNameResolverName = propertyNameResolverTypeName
};
generationDiagnostic = new GenerationDiagnostic();
var documentGenerationDiagnostic = new DocumentGenerationDiagnostic();
if (documentVariantElementNames?.Count > 1)
{
documentGenerationDiagnostic.Errors.Add(new GenerationError
{
Message = string.Format(
SpecificationGenerationMessages.MoreThanOneVariantNameNotAllowed,
documentVariantElementNames.First())
});
}
IList<string> serializedOperationElements = operationElements.Select(i => i.ToString()).ToList();
// Operation config elements can contain the types that needs to be fetched too,
// so add it to the list of operation elements which will be used to fetch type information.
if (operationConfigElement!=null)
{
serializedOperationElements.Add(operationConfigElement.ToString());
}
#if !NETFRAMEWORK
var assemblyLoader = new AssemblyLoader.AssemblyLoader();
assemblyLoader.RegisterAssemblyPaths(contractAssemblyPaths);
var internalGenerationContextAsString = new AssemblyLoader.AssemblyLoader().BuildInternalGenerationContext(
contractAssemblyPaths,
serializedOperationElements,
propertyElements.Select(i => i.ToString()).ToList(),
documentVariantElementNames.FirstOrDefault(),
internalSchemaGenerationSettings);
internalGenerationContext =
(InternalGenerationContext)JsonConvert.DeserializeObject(
internalGenerationContextAsString,
typeof(InternalGenerationContext));
#else
using (var isolatedDomain = new AppDomainCreator<AssemblyLoader.AssemblyLoader>())
{
isolatedDomain.Object.RegisterAssemblyPaths(contractAssemblyPaths);
var internalGenerationContextAsString = isolatedDomain.Object.BuildInternalGenerationContext(
contractAssemblyPaths,
serializedOperationElements,
propertyElements.Select(i => i.ToString()).ToList(),
documentVariantElementNames.FirstOrDefault(),
internalSchemaGenerationSettings);
internalGenerationContext =
(InternalGenerationContext)JsonConvert.DeserializeObject(
internalGenerationContextAsString,
typeof(InternalGenerationContext));
}
#endif
GenerationContext generationContext = internalGenerationContext.ToGenerationContext();
var operationGenerationDiagnostics = GenerateSpecificationDocuments(
generationContext,
operationElements,
operationConfigElement,
documentVariantElementNames.FirstOrDefault(),
out var documents);
foreach (var operationGenerationDiagnostic in operationGenerationDiagnostics)
{
generationDiagnostic.OperationGenerationDiagnostics.Add(
new OperationGenerationDiagnostic(operationGenerationDiagnostic));
}
var referenceRegistryManager = new ReferenceRegistryManager(_openApiDocumentGenerationSettings);
foreach (var variantInfoDocumentValuePair in documents)
{
var openApiDocument = variantInfoDocumentValuePair.Value;
foreach (var documentFilter in _documentFilters)
{
var generationErrors = documentFilter.Apply(
openApiDocument,
annotationXmlDocuments,
new DocumentFilterSettings
{
OpenApiDocumentVersion = openApiDocumentVersion,
OpenApiInfoDescription = openApiInfoDescription,
ReferenceRegistryManager = referenceRegistryManager
},
_openApiDocumentGenerationSettings);
foreach(var error in generationErrors)
{
documentGenerationDiagnostic.Errors.Add(error);
}
}
foreach (var filter in _postProcessingDocumentFilters)
{
var generationErrors = filter.Apply(
openApiDocument,
new PostProcessingDocumentFilterSettings
{
OperationGenerationDiagnostics = operationGenerationDiagnostics
});
foreach (var error in generationErrors)
{
documentGenerationDiagnostic.Errors.Add(error);
}
}
referenceRegistryManager.SecuritySchemeReferenceRegistry.References.CopyInto(
openApiDocument.Components.SecuritySchemes);
}
if (documentConfigElement != null)
{
foreach (var documentConfigFilter in _documentConfigFilters)
{
var generationErrors = documentConfigFilter.Apply(
documents,
documentConfigElement,
annotationXmlDocuments,
new DocumentConfigFilterSettings());
foreach (var error in generationErrors)
{
documentGenerationDiagnostic.Errors.Add(error);
}
}
}
var failedOperations = generationDiagnostic.OperationGenerationDiagnostics
.Where(i => i.Errors.Count > 0);
if (failedOperations.Any())
{
var totalOperationsCount = generationDiagnostic.OperationGenerationDiagnostics.Count();
var exception = new UnableToGenerateAllOperationsException(
totalOperationsCount - failedOperations.Count(), totalOperationsCount);
documentGenerationDiagnostic.Errors.Add(
new GenerationError
{
ExceptionType = exception.GetType().Name,
Message = exception.Message
});
}
generationDiagnostic.DocumentGenerationDiagnostic = documentGenerationDiagnostic;
return documents;
}
catch (Exception e)
{
generationDiagnostic = new GenerationDiagnostic
{
DocumentGenerationDiagnostic =
new DocumentGenerationDiagnostic
{
Errors =
{
new GenerationError
{
ExceptionType = e.GetType().Name,
Message = string.Format(SpecificationGenerationMessages.UnexpectedError, e)
}
}
}
};
return openApiDocuments;
}
}