22// Licensed under the MIT license.
33
44using System ;
5+ using System . Collections . Generic ;
6+ using System . IO ;
7+ using System . Threading . Tasks ;
58using Microsoft . OpenApi . Exceptions ;
69using Microsoft . OpenApi . Extensions ;
710using Microsoft . OpenApi . Interfaces ;
@@ -50,24 +53,43 @@ public OpenApiDocument Read(YamlDocument input, out OpenApiDiagnostic diagnostic
5053 // Parse the OpenAPI Document
5154 document = context . Parse ( input ) ;
5255
53- // Resolve References if requested
54- switch ( _settings . ReferenceResolution )
56+ ResolveReferences ( diagnostic , document ) ;
57+ }
58+ catch ( OpenApiException ex )
59+ {
60+ diagnostic . Errors . Add ( new OpenApiError ( ex ) ) ;
61+ }
62+
63+ // Validate the document
64+ if ( _settings . RuleSet != null && _settings . RuleSet . Rules . Count > 0 )
65+ {
66+ var errors = document . Validate ( _settings . RuleSet ) ;
67+ foreach ( var item in errors )
5568 {
56- case ReferenceResolutionSetting . ResolveAllReferences :
57- throw new ArgumentException ( Properties . SRResource . CannotResolveRemoteReferencesSynchronously ) ;
58- case ReferenceResolutionSetting . ResolveLocalReferences :
59- var resolver = new OpenApiReferenceResolver ( document ) ;
60- var walker = new OpenApiWalker ( resolver ) ;
61- walker . Walk ( document ) ;
62- foreach ( var item in resolver . Errors )
63- {
64- diagnostic . Errors . Add ( item ) ;
65- }
66- break ;
67- case ReferenceResolutionSetting . DoNotResolveReferences :
68- break ;
69+ diagnostic . Errors . Add ( item ) ;
6970 }
7071 }
72+
73+ return document ;
74+ }
75+
76+ public async Task < ReadResult > ReadAsync ( YamlDocument input )
77+ {
78+ var diagnostic = new OpenApiDiagnostic ( ) ;
79+ var context = new ParsingContext ( diagnostic )
80+ {
81+ ExtensionParsers = _settings . ExtensionParsers ,
82+ BaseUrl = _settings . BaseUrl
83+ } ;
84+
85+ OpenApiDocument document = null ;
86+ try
87+ {
88+ // Parse the OpenAPI Document
89+ document = context . Parse ( input ) ;
90+
91+ await ResolveReferencesAsync ( diagnostic , document ) ;
92+ }
7193 catch ( OpenApiException ex )
7294 {
7395 diagnostic . Errors . Add ( new OpenApiError ( ex ) ) ;
@@ -83,8 +105,71 @@ public OpenApiDocument Read(YamlDocument input, out OpenApiDiagnostic diagnostic
83105 }
84106 }
85107
86- return document ;
108+ return new ReadResult ( )
109+ {
110+ OpenApiDocument = document ,
111+ OpenApiDiagnostic = diagnostic
112+ } ;
113+ }
114+
115+
116+ private void ResolveReferences ( OpenApiDiagnostic diagnostic , OpenApiDocument document )
117+ {
118+ // Resolve References if requested
119+ switch ( _settings . ReferenceResolution )
120+ {
121+ case ReferenceResolutionSetting . ResolveAllReferences :
122+ throw new ArgumentException ( "Cannot resolve all references via a synchronous call. Use ReadAsync." ) ;
123+ case ReferenceResolutionSetting . ResolveLocalReferences :
124+ var errors = document . ResolveReferences ( false ) ;
125+
126+ foreach ( var item in errors )
127+ {
128+ diagnostic . Errors . Add ( item ) ;
129+ }
130+ break ;
131+ case ReferenceResolutionSetting . DoNotResolveReferences :
132+ break ;
133+ }
87134 }
135+
136+ private async Task ResolveReferencesAsync ( OpenApiDiagnostic diagnostic , OpenApiDocument document )
137+ {
138+ List < OpenApiError > errors = new List < OpenApiError > ( ) ;
139+
140+ // Resolve References if requested
141+ switch ( _settings . ReferenceResolution )
142+ {
143+ case ReferenceResolutionSetting . ResolveAllReferences :
144+
145+ // Create workspace for all documents to live in.
146+ var openApiWorkSpace = new OpenApiWorkspace ( ) ;
147+
148+ // Load this root document into the workspace
149+ var streamLoader = new DefaultStreamLoader ( ) ;
150+ var workspaceLoader = new OpenApiWorkspaceLoader ( openApiWorkSpace , _settings . CustomExternalLoader ?? streamLoader , _settings ) ;
151+ await workspaceLoader . LoadAsync ( new OpenApiReference ( ) { ExternalResource = "/" } , document ) ;
152+
153+ // Resolve all references in all the documents loaded into the OpenApiWorkspace
154+ foreach ( var doc in openApiWorkSpace . Documents )
155+ {
156+ errors . AddRange ( doc . ResolveReferences ( true ) ) ;
157+ }
158+ break ;
159+ case ReferenceResolutionSetting . ResolveLocalReferences :
160+ errors . AddRange ( document . ResolveReferences ( false ) ) ;
161+ break ;
162+ case ReferenceResolutionSetting . DoNotResolveReferences :
163+ break ;
164+ }
165+
166+ foreach ( var item in errors )
167+ {
168+ diagnostic . Errors . Add ( item ) ;
169+ }
170+ }
171+
172+
88173 /// <summary>
89174 /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element.
90175 /// </summary>
0 commit comments