diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 6686bba75..ed791e58b 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -6,13 +6,14 @@ trigger: branches: include: - main - - dev - support/v1 + tags: + include: + - 'v*' pr: branches: include: - main - - dev - support/v1 variables: buildPlatform: 'Any CPU' @@ -194,7 +195,7 @@ extends: content: '*.nupkg' - stage: deploy - condition: and(or(contains(variables['build.sourceBranch'], 'refs/heads/main'),contains(variables['build.sourceBranch'], 'refs/heads/support/v1')), succeeded()) + condition: and(contains(variables['build.sourceBranch'], 'refs/tags/v'), succeeded()) dependsOn: build jobs: - deployment: deploy_hidi @@ -305,18 +306,10 @@ extends: condition: succeededOrFailed() inputs: gitHubConnection: 'Github-MaggieKimani1' - action: create + action: edit tagSource: userSpecifiedTag - tag: '$(artifactVersion)' - title: '$(artifactVersion)' + tag: 'v$(artifactVersion)' releaseNotesSource: inline assets: '$(Pipeline.Workspace)\**\*.exe' - changeLogType: issueBased - changeLogLabels: '[ - { "label" : "feature-work", "feature", "displayName" : "New Features", "state" : "closed" }, - { "label" : "enhancement", "V2-Enhancement", "displayName" : "Enhancements", "state" : "closed" }, - { "label" : "bug", "bug-fix", "displayName" : "Bugs", "state" : "closed" }, - { "label" : "documentation", "doc", "displayName" : "Documentation", "state" : "closed"}, - { "label" : "dependencies", "displayName" : "Package Updates", "state" : "closed" } - ]' + addChangeLog: false diff --git a/.github/release-please.yml b/.github/release-please.yml new file mode 100644 index 000000000..c821fc166 --- /dev/null +++ b/.github/release-please.yml @@ -0,0 +1,7 @@ +manifest: true +primaryBranch: main +handleGHRelease: true +branches: + - branch: support/v1 + manifest: true + handleGHRelease: true \ No newline at end of file diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4224ace24..776426049 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,7 +2,7 @@ name: CodeQL Analysis on: push: - branches: [ main, dev ] + branches: [ main, support/v1 ] pull_request: schedule: - cron: '0 8 * * *' diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 93c8f3e87..ece97b194 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,11 +2,13 @@ name: Publish Docker image on: workflow_dispatch: push: - branches: [main, dev, support/v1] - paths: ['src/Microsoft.OpenApi.Hidi/**', '.github/workflows/**'] + tags: ["v*"] + branches: [main] + pull_request: env: REGISTRY: msgraphprod.azurecr.io IMAGE_NAME: public/openapi/hidi + PREVIEW_BRANCH: "refs/heads/main" jobs: push_to_registry: environment: @@ -28,14 +30,24 @@ jobs: echo "::set-output name=version::${version}" shell: pwsh id: getversion + - name: Get truncated run number + if: contains(github.ref, env.PREVIEW_BRANCH) + id: runnumber + run: echo "runnumber=$(echo ${{ github.run_number }} | awk '{ print substr($0, length($0)-3, length($0)) }')" >> $GITHUB_OUTPUT + - name: Get current date + if: contains(github.ref, env.PREVIEW_BRANCH) + id: date + run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT - name: Push to registry - Nightly - if: ${{ github.ref == 'refs/heads/dev' }} + if: contains(github.ref, env.PREVIEW_BRANCH) uses: docker/build-push-action@v6.13.0 with: push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.getversion.outputs.version }}-preview.${{ steps.date.outputs.date }}${{ steps.runnumber.outputs.runnumber }} + build-args: | + version_suffix=preview.${{ steps.date.outputs.date }}${{ steps.runnumber.outputs.runnumber }} - name: Push to registry - Release - if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/support/v1' }} + if: contains(github.ref, 'refs/tags/v') uses: docker/build-push-action@v6.13.0 with: push: true diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 000000000..da56a96bd --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "2.0.0-preview7" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..ca1a04854 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,153 @@ +# Changelog + +## [2.0.0-preview7](https://github.com/microsoft/OpenAPI.NET/compare/v2.0.0-preview6...v2.0.0-preview7) (2025-02-06) + + +### Bug Fixes + +* do not write null for types on parameters in v2 ([f889937](https://github.com/microsoft/OpenAPI.NET/commit/f8899379d34054e919c670ab2f8dca876bc418d5)) +* do not write null for types on parameters in v2 ([4aef7b7](https://github.com/microsoft/OpenAPI.NET/commit/4aef7b7aa4d6f19be86f7bdaf1c37edb7d174317)) + +## [2.0.0-preview6](https://github.com/microsoft/openapi.net/compare/2.0.0-preview5...v2.0.0-preview6) (2025-02-05) + + +### Features + +* adds a net8 target to benefit from all the conditional compilation ([a201aa2](https://github.com/microsoft/openapi.net/commit/a201aa237c39ab6748db0bfebd7d8c7be7ce4530)) +* adds components registration method for schemas ([10e548a](https://github.com/microsoft/openapi.net/commit/10e548ac943d6e87b132a2fcd3784c21d320346d)) +* adds deconstructor to read result ([79336f6](https://github.com/microsoft/openapi.net/commit/79336f6b1432c33f612cfc5c8ac9c79abdc04659)) +* adds deconstructor to read result ([d8c1593](https://github.com/microsoft/openapi.net/commit/d8c159331c230154236faafc315d008c61f3eb7b)) +* adds to identifier mapping to non nullable enum ([bd9622e](https://github.com/microsoft/openapi.net/commit/bd9622e239d5a5b2b4629d2f371f674775193af5)) +* bumps target OAS version to 3.1.1 ([9e8d8a4](https://github.com/microsoft/openapi.net/commit/9e8d8a4f46a6ae79d8bb53e18ff6e9d159388893)) +* configure AOT for trimming compatibility ([b4f9c3e](https://github.com/microsoft/openapi.net/commit/b4f9c3edc62e67b588e0acc04ea843f1a3bf0a76)) +* makes document optional ([754f763](https://github.com/microsoft/openapi.net/commit/754f763c2b148c04f0ba11b9c8e948557cc91b14)) +* makes the reference interface covariant ([7405f3c](https://github.com/microsoft/openapi.net/commit/7405f3c0c2d48b9b124a28796c3a7e9bce909aa7)) +* splits described and summarized interfaces ([2a10cd9](https://github.com/microsoft/openapi.net/commit/2a10cd95d254001c397a7cd28568e468800e6644)) + + +### Bug Fixes + +* 3.0 serialization when type is set to null ([920a51a](https://github.com/microsoft/openapi.net/commit/920a51a9170eb76921fd0e6529461e7681ac4c19)) +* a bug where 3.0 downcast of type null would not work ([6b636d5](https://github.com/microsoft/openapi.net/commit/6b636d53a7842e3eaf5fa70a91bc27c72be14e47)) +* a bug where 3.0 downcast of type null would not work ([ac05342](https://github.com/microsoft/openapi.net/commit/ac05342befbe51944cf3a1c966d564077e8e28ea)) +* a flaky behaviour for format property serialization ([3ea1fa9](https://github.com/microsoft/openapi.net/commit/3ea1fa981ec4d94909358e1c70c0904a2e3c4269)) +* a flaky behaviour for format property serialization ([52981d4](https://github.com/microsoft/openapi.net/commit/52981d4cebf4831f94dd59968231740e7891c5a3)) +* additional 3.1.0 constants after merge and v2 release ([9e8d8a4](https://github.com/microsoft/openapi.net/commit/9e8d8a4f46a6ae79d8bb53e18ff6e9d159388893)) +* adds generic shallow copy method to avoid inadvertent conversions of references to schemas ([e4c14a4](https://github.com/microsoft/openapi.net/commit/e4c14a451d9d50bcae0cf9b74162033cb2954a72)) +* adds missing culture argument to date serialization ([45329e4](https://github.com/microsoft/openapi.net/commit/45329e4e5b3606964e85bbfdece4b5f239865353)) +* adds missing null prop operator to proxy properties ([8361069](https://github.com/microsoft/openapi.net/commit/83610696a0c026071308d7247fab914f4db72190)) +* adds missing null propagation operators for callback and header references ([0cb4ccb](https://github.com/microsoft/openapi.net/commit/0cb4ccb925ab54e15351cbf2b0f4ae58c6b866c8)) +* adds support for all component types ([8a73b54](https://github.com/microsoft/openapi.net/commit/8a73b540e88bd18aeef27e86e41dbec3e7e1d2cd)) +* aligns callback parameter name with interface ([68b25cc](https://github.com/microsoft/openapi.net/commit/68b25cc5cc9ffd809a45ce532200ce3262f39ad2)) +* aligns missing properties for override ([e3325b9](https://github.com/microsoft/openapi.net/commit/e3325b9d4cedee6a9734899906e938888f023506)) +* aligns parameter name with interface definition for example ([d7e1f91](https://github.com/microsoft/openapi.net/commit/d7e1f919ee61e7cd4596f216890e16c7719e99c9)) +* aligns reference copy constructors ([ce93aa7](https://github.com/microsoft/openapi.net/commit/ce93aa7a23280b1fb60b9bc4e5ca4a070414fb0c)) +* aligns to null propagation operator ([8d57b81](https://github.com/microsoft/openapi.net/commit/8d57b81d7122c9ffad4f1c348879cc6df971617c)) +* allow registration of component references ([14750dc](https://github.com/microsoft/openapi.net/commit/14750dcabe29805479c3fed10152dee1ac4111af)) +* an empty security requirement should not result in an object during serialization ([1c6fd8e](https://github.com/microsoft/openapi.net/commit/1c6fd8e8ff38d0259af7fbd9903f361ecfb19225)) +* build passes ([ea68427](https://github.com/microsoft/openapi.net/commit/ea68427110e5f789019b46885ea45f8f6b975c53)) +* callback reference proxy implementation ([028d60b](https://github.com/microsoft/openapi.net/commit/028d60bd4003f54f6f130e56400cd7533951e1f2)) +* callback reference proxy implementation ([2cbb0fa](https://github.com/microsoft/openapi.net/commit/2cbb0fa352ecaf09014f26ab5fddc8ca89e63c2c)) +* components schema copy ([88daad5](https://github.com/microsoft/openapi.net/commit/88daad5d31fee2f4826be9717ece808495d9b4d8)) +* conditional version for extension causes invalid json ([4030c1f](https://github.com/microsoft/openapi.net/commit/4030c1fda6a04006326e76c8a2ca7ffd98e2d1d6)) +* conditional version for extension causes invalid json ([0ce92cc](https://github.com/microsoft/openapi.net/commit/0ce92cc948869e0d5eb46d388559405c9b412b06)) +* date time and date time offset shifting zones ([a6a44a7](https://github.com/microsoft/openapi.net/commit/a6a44a7e3d271a2cc88fda02aabec944402a32a9)) +* default settings in case of null value ([ab2ddf0](https://github.com/microsoft/openapi.net/commit/ab2ddf0f264ccaf6efbf127c23be00adec51be1f)) +* do not allow null argument for example copy constructor ([aa80b19](https://github.com/microsoft/openapi.net/commit/aa80b1968d9ec6ad26f8b45578040026883d5890)) +* do not copy host document as it negatively impact performance ([1043e4e](https://github.com/microsoft/openapi.net/commit/1043e4e3d2fbe4bf84aae453c5d76ce5672f64b6)) +* do not copy host document as it negatively impact performance ([a46e857](https://github.com/microsoft/openapi.net/commit/a46e8578519c85b9455e41ccbeebeb8740252ae3)) +* do not emit a type array in 3.1 when unnecessary ([3b3d0e6](https://github.com/microsoft/openapi.net/commit/3b3d0e6da51f7958285b8aa5be5d1eb73ec69acd)) +* draft security scheme reference proxy design pattern ([1bd2624](https://github.com/microsoft/openapi.net/commit/1bd2624dcb6751c9f31ecec422d5ec9852370397)) +* empty security requirements are actually valid. to negate the document ones ([42bd396](https://github.com/microsoft/openapi.net/commit/42bd3960d799af3d522ba122ce713a7d418c98ba)) +* enum description number values ([ff7b4a9](https://github.com/microsoft/openapi.net/commit/ff7b4a99351661b7dd26e24bd4daa9e61d39ff27)) +* enum description number values ([e29e24c](https://github.com/microsoft/openapi.net/commit/e29e24c58f51af4f6a39aeb65041dbd7f7ab888f)) +* enum parsing when encountering unknown values should not default to first member ([d4e155b](https://github.com/microsoft/openapi.net/commit/d4e155b6d66887f28cbb13fb22ba0d70eabc4139)) +* enum parsing when encountering unknown values should not default to first member ([9d07ebb](https://github.com/microsoft/openapi.net/commit/9d07ebb4b70bdd641748270a831df031d35b7ec4)) +* extensions collection initialization ([4f28b65](https://github.com/microsoft/openapi.net/commit/4f28b657310b90c82a5b5af9f91ef6e097847a97)) +* extraneous null prop removal ([1006879](https://github.com/microsoft/openapi.net/commit/10068797577e14ed4ebf6909face0aef7e3f7d56)) +* failing unit test after merge ([a4ac872](https://github.com/microsoft/openapi.net/commit/a4ac872c3336fad2f6a4e05a7602ea76f6db9b49)) +* failing unit tests for security scheme references in security requirements ([d2e4111](https://github.com/microsoft/openapi.net/commit/d2e4111198a435547bacfe62a5626e4d78114f8d)) +* fixes inlining override when they should not happen ([704943c](https://github.com/microsoft/openapi.net/commit/704943c28f87257e896d1a79eb6962d60f719bec)) +* fixes invalid OAI document for unit tests ([837f000](https://github.com/microsoft/openapi.net/commit/837f00081a1e52200b90adeac6e2aff32c92d296)) +* inconsistant API surface usage ([47ad76b](https://github.com/microsoft/openapi.net/commit/47ad76b4318d1a468478d4c1c82092bd5aa0eb6a)) +* last reference to copy constructor ([d87375d](https://github.com/microsoft/openapi.net/commit/d87375dc8d463fb348938acb1ed048b5a5dde166)) +* makes reference fields immutable ([fda05d4](https://github.com/microsoft/openapi.net/commit/fda05d465ef84f2c4c755aca2252e2672ad40107)) +* makes reference of holder immutable ([a182f44](https://github.com/microsoft/openapi.net/commit/a182f44bfb74ccbbb5b4bbf842693de48d60dac1)) +* makes target field read only ([89881fd](https://github.com/microsoft/openapi.net/commit/89881fd5fa28148969eba75fad07ac26d4fb4e3d)) +* missing defensive programming in copy constructors ([227d99d](https://github.com/microsoft/openapi.net/commit/227d99d23557fab82fcb7eb7d6e8fa34b486719d)) +* missing doc comment for annotations ([41759a1](https://github.com/microsoft/openapi.net/commit/41759a1cb587d38392f730dfce74e974c76189c6)) +* missing null prop operator on parameter reference ([019eb99](https://github.com/microsoft/openapi.net/commit/019eb99fc26f323f7a5bc79609954d237b1c0bfc)) +* missing property rename ([2443fa0](https://github.com/microsoft/openapi.net/commit/2443fa0d3da5ec4ef09d9e6cae2491a117fac77b)) +* multiple performance fixes for type serialization ([bd9622e](https://github.com/microsoft/openapi.net/commit/bd9622e239d5a5b2b4629d2f371f674775193af5)) +* multiple performance fixes for type serialization feat: adds to identifier mapping to non nullable enum ([5fef51c](https://github.com/microsoft/openapi.net/commit/5fef51c4cb3685eceabfdbb21abb1e88a87571a9)) +* multiple unit test failures ([2f171a3](https://github.com/microsoft/openapi.net/commit/2f171a3476ea0f3227ecdcb724f1d1af5406ec0e)) +* null flag comparison ([081e251](https://github.com/microsoft/openapi.net/commit/081e2511b9df964ad74f7cb0e48761977e50cc45)) +* null propagation for most failed reference lookup ([7994691](https://github.com/microsoft/openapi.net/commit/7994691db279c23e3ac120a54b5d96cc7f88ae3f)) +* null reference check ([a5023d6](https://github.com/microsoft/openapi.net/commit/a5023d659b7adaedbe18853c297e78ac12e22823)) +* Open API header proxy design pattern implementation ([77e0ad1](https://github.com/microsoft/openapi.net/commit/77e0ad10ca213c449523e9ff1802da6a6bd800e2)) +* open API link reference proxy design pattern implementation ([6a96462](https://github.com/microsoft/openapi.net/commit/6a9646278377d0f81289c34ad25b2102b488dd9e)) +* open API link reference proxy design pattern implementation ([376e54d](https://github.com/microsoft/openapi.net/commit/376e54de6d419c4e6673111538140bedafd7896e)) +* open api response reference should not clone objects ([4243873](https://github.com/microsoft/openapi.net/commit/42438730a57acada699a017da41838d0d54e141d)) +* open api schema reference proxy design pattern implementation ([e57d049](https://github.com/microsoft/openapi.net/commit/e57d04972c360f1367583eb9e60f750f8882f0b7)) +* open api schema reference proxy design pattern implementation ([aebefb7](https://github.com/microsoft/openapi.net/commit/aebefb76094e71718b1d60691e9ac12a95a25283)) +* parameter reference proxy design pattern implementation ([ed6ffa1](https://github.com/microsoft/openapi.net/commit/ed6ffa1d4a59857cc57f6286d383ff3a9661a00e)) +* parameter reference proxy design pattern implementation ([eeb79a4](https://github.com/microsoft/openapi.net/commit/eeb79a4a7700d6fb56fbcbbe6913d224fa126167)) +* passes missing host document references to all layers ([d7c4621](https://github.com/microsoft/openapi.net/commit/d7c462163272a26705f9b30f2a6c407c74acfc0f)) +* passes missing host document references to all layers ([ff1406c](https://github.com/microsoft/openapi.net/commit/ff1406c60082727851d22003211faaa4e876d2e8)) +* path item reference implementation ([56f291b](https://github.com/microsoft/openapi.net/commit/56f291b325682e72f1f347097be2fb9786c628b1)) +* path item reference implementation ([c725267](https://github.com/microsoft/openapi.net/commit/c7252677814eec7a9a8ff6f0f3a51f5e113f5f19)) +* potential NRT ([9db6e2d](https://github.com/microsoft/openapi.net/commit/9db6e2d3ce9043ff6b702060eda75290aa37b401)) +* potential NRT for net8 build ([f517deb](https://github.com/microsoft/openapi.net/commit/f517deb6c7f68947a4a25da5b76ed1ee94d307e2)) +* proxy design pattern implementation for OpenAPiExample ([cc28ff2](https://github.com/microsoft/openapi.net/commit/cc28ff27446dae0fc0e9f9f44dafd6df6e8fc243)) +* proxy design pattern implementation for request body ([425335e](https://github.com/microsoft/openapi.net/commit/425335eb46d4a48104046af62265ba0ca6a1ec7b)) +* references callback writer ([88ad997](https://github.com/microsoft/openapi.net/commit/88ad99759d8735824c7a70321ed7efc164633f06)) +* removes all obsolete APIs ([e861c08](https://github.com/microsoft/openapi.net/commit/e861c08442fe7b2f1b0e4079d4a007e525a75ca9)) +* removes extraneuous null prop op in copy constructor ([227d99d](https://github.com/microsoft/openapi.net/commit/227d99d23557fab82fcb7eb7d6e8fa34b486719d)) +* removes nullable property that shouldn't be part of dom ([4d9c17b](https://github.com/microsoft/openapi.net/commit/4d9c17b7287b27b9058828765722f55eb378e40a)) +* removes redundant assignment ([8d70195](https://github.com/microsoft/openapi.net/commit/8d701955f24801b495dfd4b3b7a2351b499355b2)) +* removes unnecessary null prop in copy constructor ([aa993b1](https://github.com/microsoft/openapi.net/commit/aa993b10ff72fb18f7dc3f49d87586662188a381)) +* removes unused parameters ([de9d979](https://github.com/microsoft/openapi.net/commit/de9d979ec3f53fb7a86c43309f7e87d20d89d22a)) +* removes unused parameters ([9cd7aae](https://github.com/microsoft/openapi.net/commit/9cd7aaea76316b3944e8a549db9aad3a3155b51b)) +* removes useless condition for null check ([4a50c77](https://github.com/microsoft/openapi.net/commit/4a50c77a90f0e9810b4912cbb694883921c508cd)) +* removes useless virtual definitions in components ([af3038a](https://github.com/microsoft/openapi.net/commit/af3038a0fcee46c4806382fe061e4f2e7059fdbe)) +* removes virtual modifier in MediaType ([4dfc9b8](https://github.com/microsoft/openapi.net/commit/4dfc9b8c533d454cefa3d576adb4d3d422747d16)) +* request body references are converted to v2 properly ([b84ea19](https://github.com/microsoft/openapi.net/commit/b84ea194a16e03a1f2b6f56af892eb6288d5627a)) +* response reference proxy design pattern implementation ([8103c20](https://github.com/microsoft/openapi.net/commit/8103c20f669eb9c127aec3baaaafda3987381d9b)) +* response reference proxy design pattern implementation ([5b4003b](https://github.com/microsoft/openapi.net/commit/5b4003bd04d59fd460280fa06e6151b0203680cb)) +* restores default constructor for ISerializable implementation ([778184f](https://github.com/microsoft/openapi.net/commit/778184ff608cd4172de689684272b2d7a8627339)) +* returns reference instead of null ([45e40fa](https://github.com/microsoft/openapi.net/commit/45e40fa675570fc382d4a72684a009b567d45118)) +* sets hidi version to a preview ([975b1bf](https://github.com/microsoft/openapi.net/commit/975b1bfa563bc36ad8031de934af158cb807bca8)) +* sets hidi version to a preview ([8999336](https://github.com/microsoft/openapi.net/commit/899933636f15991add45e367befd1c30c93bcf2c)) +* shallow copy for callback ([4ea87ef](https://github.com/microsoft/openapi.net/commit/4ea87efad0edde89f2e29c0c495a33a4467ba939)) +* shallow copy for example ([9bc3044](https://github.com/microsoft/openapi.net/commit/9bc30443ab95fd05b0b328c13b7e36e911628dda)) +* shallow copy for parameter link path item and request body ([9af6f30](https://github.com/microsoft/openapi.net/commit/9af6f30719c7e0718798df98096f1679f74c20e7)) +* side effects in tag references ([717deb0](https://github.com/microsoft/openapi.net/commit/717deb08d2198519a69a3ccf701f46dac229e608)) +* side effects in tag references ([878593b](https://github.com/microsoft/openapi.net/commit/878593b7a7e6ff1f2adc6965608c46e5f8ce8f38)) +* single copy and maintain for references ([30ee6ed](https://github.com/microsoft/openapi.net/commit/30ee6ed9ac8e6a6a7d1931bed9da22e0116ec9af)) +* specifies encoding for net fx ([95dafe6](https://github.com/microsoft/openapi.net/commit/95dafe60a103293acba6c6aa16c4c780e7b576c9)) +* specifies encoding for net fx ([cd13481](https://github.com/microsoft/openapi.net/commit/cd13481f4e3a883186d10b3af63cbd928a17c8ba)) +* support non-standard MIME type in response header ([50ddca2](https://github.com/microsoft/openapi.net/commit/50ddca2f72a9b4eef21c45fdd1c978e8f6f32eb3)) +* switches header to shallow copy ([2a42c36](https://github.com/microsoft/openapi.net/commit/2a42c36eb7d83c0b83f8263b7989f84c5ddf911d)) +* tag reference proxy design pattern implementation ([46e08d4](https://github.com/microsoft/openapi.net/commit/46e08d4b53e756db5d717337488c9bb787ec8ee7)) +* tag, response, and security scheme shallow copy ([7ac149c](https://github.com/microsoft/openapi.net/commit/7ac149c70d69c357aa0dc0d8e29e975a886226f9)) +* updates public api file ([b727581](https://github.com/microsoft/openapi.net/commit/b727581d6fd1d814b5c1887400cb48f06dd96362)) +* updates public API surface with net8 target ([1a1e013](https://github.com/microsoft/openapi.net/commit/1a1e0135e977440be91e64d14e3d2b094238facd)) +* uses backing fields instead of schema copy ([6f4e7a2](https://github.com/microsoft/openapi.net/commit/6f4e7a245376cb816367ff86c497cbba023b6faf)) +* uses the json node clone API to avoid unecessary allocs ([818414d](https://github.com/microsoft/openapi.net/commit/818414d73a351447a403e8555c140b180de5d375)) +* v2 references for properties do not work as expected ([aa90edf](https://github.com/microsoft/openapi.net/commit/aa90edf1b624e1bd2381700f2d8b659507bf0119)) +* v2 references for properties do not work as expected ([ec9c01b](https://github.com/microsoft/openapi.net/commit/ec9c01b9b873d02ab2682ceb5fb9ac509a931781)) +* v2 request body content null propagation ([6d064c4](https://github.com/microsoft/openapi.net/commit/6d064c4b967f7f9262a85438d27cf7bf2ccc412c)) +* v2 request body content null propagation ([8b4833c](https://github.com/microsoft/openapi.net/commit/8b4833cce98cb8d8c782ceed8d5d122357b71065)) +* visibility of serialize internal methods ([dc8a757](https://github.com/microsoft/openapi.net/commit/dc8a7572ec436c1ed35f5a6208c6aa868702dc0f)) + + +### Performance Improvements + +* avoid round trip serialization ([a6a44a7](https://github.com/microsoft/openapi.net/commit/a6a44a7e3d271a2cc88fda02aabec944402a32a9)) + +## Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..a08924c7b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,52 @@ +# Contributing to OpenAPI.net + +OpenAPI.net is a mono-repo containing source code for the following packages: + +## Libraries + +| Library | NuGet Release | +|----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Microsoft.OpenAPI](./src/Microsoft.OpenAPI/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI/) | +| [Microsoft.OpenAPI.Readers](./src/Microsoft.OpenAPI.Readers/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI.Readers?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI.Readers/) | +| [Microsoft.OpenAPI.Hidi](./src/Microsoft.OpenAPI.Hidi/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI.Hidi?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI.Hidi/) | + +OpenAPI.net is open to contributions. There are a couple of different recommended paths to get contributions into the released version of this library. + +__NOTE__ A signed a contribution license agreement is required for all contributions, and is checked automatically on new pull requests. Please read and sign [the agreement](https://cla.microsoft.com/) before starting any work for this repository. + +## File issues + +The best way to get started with a contribution is to start a dialog with the owners of this repository. Sometimes features will be under development or out of scope for this SDK and it's best to check before starting work on contribution. Discussions on bugs and potential fixes could point you to the write change to make. + +## Submit pull requests for bug fixes and features + +Feel free to submit a pull request with a linked issue against the __main__ branch. The main branch will be updated frequently. +## Commit message format + +To support our automated release process, pull requests are required to follow the [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/) +format. +Each commit message consists of a __header__, an optional __body__ and an optional __footer__. The header is the first line of the commit and +MUST have a __type__ (see below for a list of types) and a __description__. An optional __scope__ can be added to the header to give extra context. + +``` +[optional scope]: + + + + +``` + +The recommended commit types used are: + +- __feat__ for feature updates (increments the _minor_ version) +- __fix__ for bug fixes (increments the _patch_ version) +- __perf__ for performance related changes e.g. optimizing an algorithm +- __refactor__ for code refactoring changes +- __test__ for test suite updates e.g. adding a test or fixing a test +- __style__ for changes that don't affect the meaning of code. e.g. formatting changes +- __docs__ for documentation updates e.g. ReadMe update or code documentation updates +- __build__ for build system changes (gradle updates, external dependency updates) +- __ci__ for CI configuration file changes e.g. updating a pipeline +- __chore__ for miscallaneous non-sdk changesin the repo e.g. removing an unused file + +Adding an exclamation mark after the commit type (`feat!`) or footer with the prefix __BREAKING CHANGE:__ will cause an increment of the _major_ version. \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 4fbb218f9..383e4fef2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,14 +12,13 @@ https://github.com/Microsoft/OpenAPI.NET © Microsoft Corporation. All rights reserved. OpenAPI .NET + 2.0.0-preview7 true - + \ No newline at end of file diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 000000000..e6d1fb148 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,33 @@ +{ + "bootstrap-sha": "8943e2ad40babb0204dedb11ad6f9273adf9cd53", + "exclude-paths": [ + ".azure-pipelines", + ".github", + ".idea", + ".vs", + ".vscode" + ], + "release-type": "simple", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-component-in-tag": false, + "include-v-in-tag": true, + "draft": false, + "prerelease": true, + "versioning": "prerelease", + "prerelease-type": "preview", + "packages": { + ".": { + "package-name": "Microsoft.OpenApi", + "changelog-path": "CHANGELOG.md", + "extra-files": [ + { + "type": "xml", + "path": "Directory.Build.props", + "xpath": "//Project/PropertyGroup/Version" + } + ] + } + }, + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" +} \ No newline at end of file diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index a6b6380d6..df632b78a 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -16,7 +16,7 @@ internal class PowerShellFormatter : OpenApiVisitorBase { private const string DefaultPutPrefix = ".Update"; private const string PowerShellPutPrefix = ".Set"; - private readonly Stack _schemaLoop = new(); + private readonly Stack _schemaLoop = new(); private static readonly Regex s_oDataCastRegex = new("(.*(?<=[a-z]))\\.(As(?=[A-Z]).*)", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); private static readonly Regex s_hashSuffixRegex = new(@"^[^-]+", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); private static readonly Regex s_oDataRefRegex = new("(?<=[a-z])Ref(?=[A-Z])", RegexOptions.Compiled, TimeSpan.FromSeconds(5)); @@ -42,7 +42,7 @@ static PowerShellFormatter() // 5. Fix anyOf and oneOf schema. // 6. Add AdditionalProperties to object schemas. - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { AddAdditionalPropertiesToSchema(schema); ResolveAnyOfSchema(schema); @@ -165,10 +165,10 @@ private static void ResolveFunctionParameters(IList parameter // Replace content with a schema object of type array // for structured or collection-valued function parameters parameter.Content = null; - parameter.Schema = new() + parameter.Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -176,11 +176,11 @@ private static void ResolveFunctionParameters(IList parameter } } - private void AddAdditionalPropertiesToSchema(OpenApiSchema schema) + private void AddAdditionalPropertiesToSchema(IOpenApiSchema schema) { - if (schema != null && !_schemaLoop.Contains(schema) && schema.Type.Equals(JsonSchemaType.Object)) + if (schema is OpenApiSchema openApiSchema && !_schemaLoop.Contains(schema) && schema.Type.Equals(JsonSchemaType.Object)) { - schema.AdditionalProperties = new() { Type = JsonSchemaType.Object }; + openApiSchema.AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Object }; /* Because 'additionalProperties' are now being walked, * we need a way to keep track of visited schemas to avoid @@ -190,39 +190,29 @@ private void AddAdditionalPropertiesToSchema(OpenApiSchema schema) } } - private static void ResolveOneOfSchema(OpenApiSchema schema) + private static void ResolveOneOfSchema(IOpenApiSchema schema) { - if (schema.OneOf?.FirstOrDefault() is { } newSchema) + if (schema is OpenApiSchema openApiSchema && schema.OneOf?.FirstOrDefault() is OpenApiSchema newSchema) { - schema.OneOf = null; - FlattenSchema(schema, newSchema); + openApiSchema.OneOf = null; + FlattenSchema(openApiSchema, newSchema); } } - private static void ResolveAnyOfSchema(OpenApiSchema schema) + private static void ResolveAnyOfSchema(IOpenApiSchema schema) { - if (schema.AnyOf?.FirstOrDefault() is { } newSchema) + if (schema is OpenApiSchema openApiSchema && schema.AnyOf?.FirstOrDefault() is OpenApiSchema newSchema) { - schema.AnyOf = null; - FlattenSchema(schema, newSchema); + openApiSchema.AnyOf = null; + FlattenSchema(openApiSchema, newSchema); } } private static void FlattenSchema(OpenApiSchema schema, OpenApiSchema newSchema) { - if (newSchema != null) - { - if (newSchema.Reference != null) - { - schema.Reference = newSchema.Reference; - schema.UnresolvedReference = true; - } - else - { - // Copies schema properties based on https://github.com/microsoft/OpenAPI.NET.OData/pull/264. - CopySchema(schema, newSchema); - } - } + if (newSchema is null) return; + // Copies schema properties based on https://github.com/microsoft/OpenAPI.NET.OData/pull/264. + CopySchema(schema, newSchema); } private static void CopySchema(OpenApiSchema schema, OpenApiSchema newSchema) @@ -253,7 +243,6 @@ private static void CopySchema(OpenApiSchema schema, OpenApiSchema newSchema) schema.Enum ??= newSchema.Enum; schema.ReadOnly = !schema.ReadOnly ? newSchema.ReadOnly : schema.ReadOnly; schema.WriteOnly = !schema.WriteOnly ? newSchema.WriteOnly : schema.WriteOnly; - schema.Nullable = !schema.Nullable ? newSchema.Nullable : schema.Nullable; schema.Deprecated = !schema.Deprecated ? newSchema.Deprecated : schema.Deprecated; } } diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 1e13eb157..b4bfa6189 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -9,7 +9,6 @@ enable hidi ./../../artifacts - 2.0.0-preview5 OpenAPI.NET CLI tool for slicing OpenAPI documents true diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index c7bf1a558..c757f4031 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -254,7 +254,7 @@ private static async Task GetOpenApiAsync(HidiOptions options, else if (!string.IsNullOrEmpty(options.OpenApi)) { stream = await GetStreamAsync(options.OpenApi, logger, cancellationToken).ConfigureAwait(false); - var result = await ParseOpenApiAsync(options.OpenApi, format, options.InlineExternal, logger, stream, cancellationToken).ConfigureAwait(false); + var result = await ParseOpenApiAsync(options.OpenApi, options.InlineExternal, logger, stream, cancellationToken).ConfigureAwait(false); document = result.Document; } else throw new InvalidOperationException("No input file path or URL provided"); @@ -351,8 +351,7 @@ private static MemoryStream ApplyFilterToCsdl(Stream csdlStream, string entitySe try { using var stream = await GetStreamAsync(openApi, logger, cancellationToken).ConfigureAwait(false); - var openApiFormat = !string.IsNullOrEmpty(openApi) ? GetOpenApiFormat(openApi, logger) : OpenApiFormat.Yaml; - result = await ParseOpenApiAsync(openApi, openApiFormat.GetDisplayName(),false, logger, stream, cancellationToken).ConfigureAwait(false); + result = await ParseOpenApiAsync(openApi, false, logger, stream, cancellationToken).ConfigureAwait(false); using (logger.BeginScope("Calculating statistics")) { @@ -380,7 +379,7 @@ private static MemoryStream ApplyFilterToCsdl(Stream csdlStream, string entitySe return result.Diagnostic.Errors.Count == 0; } - private static async Task ParseOpenApiAsync(string openApiFile, string format, bool inlineExternal, ILogger logger, Stream stream, CancellationToken cancellationToken = default) + private static async Task ParseOpenApiAsync(string openApiFile, bool inlineExternal, ILogger logger, Stream stream, CancellationToken cancellationToken = default) { ReadResult result; var stopwatch = Stopwatch.StartNew(); @@ -396,7 +395,7 @@ private static async Task ParseOpenApiAsync(string openApiFile, stri new Uri("file://" + new FileInfo(openApiFile).DirectoryName + Path.DirectorySeparatorChar) }; - result = await OpenApiDocument.LoadAsync(stream, format, settings, cancellationToken).ConfigureAwait(false); + result = await OpenApiDocument.LoadAsync(stream, settings: settings, cancellationToken: cancellationToken).ConfigureAwait(false); logger.LogTrace("{Timestamp}ms: Completed parsing.", stopwatch.ElapsedMilliseconds); diff --git a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs index 645f94319..d157a6c42 100644 --- a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs @@ -20,7 +20,7 @@ public override void Visit(IOpenApiParameter parameter) public int SchemaCount { get; set; } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { SchemaCount++; } diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj index 624fe822f..13c50aefd 100644 --- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj +++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj @@ -4,7 +4,6 @@ latest true - 2.0.0-preview5 OpenAPI.NET Readers for JSON and YAML documents true true diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 2f1ce2b37..eba4fd248 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -11,6 +11,7 @@ using SharpYaml.Serialization; using Microsoft.OpenApi.Models; using System; +using System.Linq; using System.Text; namespace Microsoft.OpenApi.Readers @@ -77,9 +78,9 @@ public ReadResult Read(MemoryStream input, } /// - public static ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null) + public static ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings) { - return _jsonReader.Read(jsonNode, settings, OpenApiConstants.Yaml); + return _jsonReader.Read(jsonNode, settings); } /// @@ -123,8 +124,12 @@ static JsonNode LoadJsonNodesFromYamlDocument(TextReader input) { var yamlStream = new YamlStream(); yamlStream.Load(input); - var yamlDocument = yamlStream.Documents[0]; - return yamlDocument.ToJsonNode(); + if (yamlStream.Documents.Any()) + { + return yamlStream.Documents[0].ToJsonNode(); + } + + throw new InvalidOperationException("No documents found in the YAML stream."); } } } diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs index 7eee12251..34a44c026 100644 --- a/src/Microsoft.OpenApi.Workbench/MainModel.cs +++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs @@ -219,7 +219,7 @@ internal async Task ParseDocumentAsync() { if (!string.IsNullOrWhiteSpace(_inputFile)) { - stream = _inputFile.StartsWith("http") ? await _httpClient.GetStreamAsync(_inputFile) + stream = _inputFile.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? await _httpClient.GetStreamAsync(_inputFile) : new FileStream(_inputFile, FileMode.Open); } else @@ -241,7 +241,7 @@ internal async Task ParseDocumentAsync() }; if (ResolveExternal && !string.IsNullOrWhiteSpace(_inputFile)) { - settings.BaseUrl = _inputFile.StartsWith("http") ? new(_inputFile) + settings.BaseUrl = _inputFile.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? new(_inputFile) : new("file://" + Path.GetDirectoryName(_inputFile) + "/"); } diff --git a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs index fbf9f3c9a..85dc824a4 100644 --- a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs @@ -20,7 +20,7 @@ public override void Visit(IOpenApiParameter parameter) public int SchemaCount { get; set; } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { SchemaCount++; } diff --git a/src/Microsoft.OpenApi/Expressions/RuntimeExpression.cs b/src/Microsoft.OpenApi/Expressions/RuntimeExpression.cs index 25792257e..69aecfd37 100644 --- a/src/Microsoft.OpenApi/Expressions/RuntimeExpression.cs +++ b/src/Microsoft.OpenApi/Expressions/RuntimeExpression.cs @@ -31,31 +31,31 @@ public static RuntimeExpression Build(string expression) { Utils.CheckArgumentNullOrEmpty(expression); - if (!expression.StartsWith(Prefix)) + if (!expression.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase)) { return new CompositeExpression(expression); } // $url - if (expression == UrlExpression.Url) + if (expression.Equals(UrlExpression.Url, StringComparison.Ordinal)) { return new UrlExpression(); } // $method - if (expression == MethodExpression.Method) + if (expression.Equals(MethodExpression.Method, StringComparison.Ordinal)) { return new MethodExpression(); } // $statusCode - if (expression == StatusCodeExpression.StatusCode) + if (expression.Equals(StatusCodeExpression.StatusCode, StringComparison.Ordinal)) { return new StatusCodeExpression(); } // $request. - if (expression.StartsWith(RequestExpression.Request)) + if (expression.StartsWith(RequestExpression.Request, StringComparison.Ordinal)) { var subString = expression.Substring(RequestExpression.Request.Length); var source = SourceExpression.Build(subString); @@ -63,7 +63,7 @@ public static RuntimeExpression Build(string expression) } // $response. - if (expression.StartsWith(ResponseExpression.Response)) + if (expression.StartsWith(ResponseExpression.Response, StringComparison.Ordinal)) { var subString = expression.Substring(ResponseExpression.Response.Length); var source = SourceExpression.Build(subString); diff --git a/src/Microsoft.OpenApi/Expressions/SourceExpression.cs b/src/Microsoft.OpenApi/Expressions/SourceExpression.cs index 8504a1e89..76a22f97d 100644 --- a/src/Microsoft.OpenApi/Expressions/SourceExpression.cs +++ b/src/Microsoft.OpenApi/Expressions/SourceExpression.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Properties; @@ -37,19 +38,19 @@ protected SourceExpression(string value) var expressions = expression.Split('.'); if (expressions.Length == 2) { - if (expression.StartsWith(HeaderExpression.Header)) + if (expression.StartsWith(HeaderExpression.Header, StringComparison.Ordinal)) { // header. return new HeaderExpression(expressions[1]); } - if (expression.StartsWith(QueryExpression.Query)) + if (expression.StartsWith(QueryExpression.Query, StringComparison.Ordinal)) { // query. return new QueryExpression(expressions[1]); } - if (expression.StartsWith(PathExpression.Path)) + if (expression.StartsWith(PathExpression.Path, StringComparison.Ordinal)) { // path. return new PathExpression(expressions[1]); @@ -57,7 +58,7 @@ protected SourceExpression(string value) } // body - if (expression.StartsWith(BodyExpression.Body)) + if (expression.StartsWith(BodyExpression.Body, StringComparison.Ordinal)) { var subString = expression.Substring(BodyExpression.Body.Length); if (string.IsNullOrEmpty(subString)) diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs index d6522ead3..c8c3b2a48 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; @@ -26,7 +27,7 @@ public static void AddExtension(this T element, string name, IOpenApiExtensio Utils.CheckArgumentNull(element); Utils.CheckArgumentNullOrEmpty(name); - if (!name.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix)) + if (!name.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase)) { throw new OpenApiException(string.Format(SRResource.ExtensionFieldNameMustBeginWithXDash, name)); } diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs index e47eff496..eea41be49 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs @@ -87,19 +87,19 @@ public static JsonSchemaType ToJsonSchemaType(this string identifier) [typeof(char)] = () => new() { Type = JsonSchemaType.String }, // Nullable types - [typeof(bool?)] = () => new() { Type = JsonSchemaType.Boolean, Nullable = true }, - [typeof(byte?)] = () => new() { Type = JsonSchemaType.String, Format = "byte", Nullable = true }, - [typeof(int?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true }, - [typeof(uint?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true }, - [typeof(long?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true }, - [typeof(ulong?)] = () => new() { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true }, - [typeof(float?)] = () => new() { Type = JsonSchemaType.Number, Format = "float", Nullable = true }, - [typeof(double?)] = () => new() { Type = JsonSchemaType.Number, Format = "double", Nullable = true }, - [typeof(decimal?)] = () => new() { Type = JsonSchemaType.Number, Format = "double", Nullable = true }, - [typeof(DateTime?)] = () => new() { Type = JsonSchemaType.String, Format = "date-time", Nullable = true }, - [typeof(DateTimeOffset?)] = () => new() { Type = JsonSchemaType.String, Format = "date-time", Nullable = true }, - [typeof(Guid?)] = () => new() { Type = JsonSchemaType.String, Format = "uuid", Nullable = true }, - [typeof(char?)] = () => new() { Type = JsonSchemaType.String, Nullable = true }, + [typeof(bool?)] = () => new() { Type = JsonSchemaType.Boolean | JsonSchemaType.Null }, + [typeof(byte?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "byte" }, + [typeof(int?)] = () => new() { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32" }, + [typeof(uint?)] = () => new() { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32" }, + [typeof(long?)] = () => new() { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int64" }, + [typeof(ulong?)] = () => new() { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int64" }, + [typeof(float?)] = () => new() { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "float" }, + [typeof(double?)] = () => new() { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" }, + [typeof(decimal?)] = () => new() { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" }, + [typeof(DateTime?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "date-time" }, + [typeof(DateTimeOffset?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "date-time" }, + [typeof(Guid?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "uuid" }, + [typeof(char?)] = () => new() { Type = JsonSchemaType.String | JsonSchemaType.Null }, [typeof(Uri)] = () => new() { Type = JsonSchemaType.String, Format = "uri" }, // Uri is treated as simple string [typeof(string)] = () => new() { Type = JsonSchemaType.String }, @@ -153,37 +153,37 @@ public static Type MapOpenApiPrimitiveTypeToSimpleType(this OpenApiSchema schema throw new ArgumentNullException(nameof(schema)); } - var type = (schema.Type.ToIdentifier(), schema.Format?.ToLowerInvariant(), schema.Nullable) switch + var type = ((schema.Type & ~JsonSchemaType.Null).ToIdentifier(), schema.Format?.ToLowerInvariant(), schema.Type & JsonSchemaType.Null) switch { - ("boolean", null, false) => typeof(bool), + ("integer" or "number", "int32", JsonSchemaType.Null) => typeof(int?), + ("integer" or "number", "int64", JsonSchemaType.Null) => typeof(long?), + ("integer", null, JsonSchemaType.Null) => typeof(long?), + ("number", "float", JsonSchemaType.Null) => typeof(float?), + ("number", "double", JsonSchemaType.Null) => typeof(double?), + ("number", null, JsonSchemaType.Null) => typeof(double?), + ("number", "decimal", JsonSchemaType.Null) => typeof(decimal?), + ("string", "byte", JsonSchemaType.Null) => typeof(byte?), + ("string", "date-time", JsonSchemaType.Null) => typeof(DateTimeOffset?), + ("string", "uuid", JsonSchemaType.Null) => typeof(Guid?), + ("string", "char", JsonSchemaType.Null) => typeof(char?), + ("boolean", null, JsonSchemaType.Null) => typeof(bool?), + ("boolean", null, _) => typeof(bool), // integer is technically not valid with format, but we must provide some compatibility - ("integer" or "number", "int32", false) => typeof(int), - ("integer" or "number", "int64", false) => typeof(long), - ("integer", null, false) => typeof(long), - ("number", "float", false) => typeof(float), - ("number", "double", false) => typeof(double), - ("number", "decimal", false) => typeof(decimal), - ("number", null, false) => typeof(double), - ("string", "byte", false) => typeof(byte), - ("string", "date-time", false) => typeof(DateTimeOffset), - ("string", "uuid", false) => typeof(Guid), - ("string", "duration", false) => typeof(TimeSpan), - ("string", "char", false) => typeof(char), - ("string", null, false) => typeof(string), - ("object", null, false) => typeof(object), - ("string", "uri", false) => typeof(Uri), - ("integer" or "number", "int32", true) => typeof(int?), - ("integer" or "number", "int64", true) => typeof(long?), - ("integer", null, true) => typeof(long?), - ("number", "float", true) => typeof(float?), - ("number", "double", true) => typeof(double?), - ("number", null, true) => typeof(double?), - ("number", "decimal", true) => typeof(decimal?), - ("string", "byte", true) => typeof(byte?), - ("string", "date-time", true) => typeof(DateTimeOffset?), - ("string", "uuid", true) => typeof(Guid?), - ("string", "char", true) => typeof(char?), - ("boolean", null, true) => typeof(bool?), + ("integer" or "number", "int32", _) => typeof(int), + ("integer" or "number", "int64", _) => typeof(long), + ("integer", null, _) => typeof(long), + ("number", "float", _) => typeof(float), + ("number", "double", _) => typeof(double), + ("number", "decimal", _) => typeof(decimal), + ("number", null, _) => typeof(double), + ("string", "byte", _) => typeof(byte), + ("string", "date-time", _) => typeof(DateTimeOffset), + ("string", "uuid", _) => typeof(Guid), + ("string", "duration", _) => typeof(TimeSpan), + ("string", "char", _) => typeof(char), + ("string", null, _) => typeof(string), + ("object", null, _) => typeof(object), + ("string", "uri", _) => typeof(Uri), _ => typeof(string), }; diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceHolder.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceHolder.cs index 74a38e04a..8883a90f5 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceHolder.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceHolder.cs @@ -8,22 +8,14 @@ namespace Microsoft.OpenApi.Interfaces /// /// A generic interface for OpenApiReferenceable objects that have a target. /// - /// Type of the target being referenced - public interface IOpenApiReferenceHolder : IOpenApiReferenceHolder where T : IOpenApiReferenceable + /// The type of the target being referenced + /// The type of the interface implemented by both the target and the reference type + public interface IOpenApiReferenceHolder : IOpenApiReferenceHolder where T : IOpenApiReferenceable, V { /// /// Gets the resolved target object. /// T Target { get; } - } - /// - /// A generic interface for OpenApiReferenceable objects that have a target. - /// - /// The type of the target being referenced - /// The type of the interface implemented by both the target and the reference type - public interface IOpenApiReferenceHolder : IOpenApiReferenceHolder where T : IOpenApiReferenceable, V - { - //TODO merge this interface with the previous once all implementations are updated /// /// Copy the reference as a target element with overrides. /// @@ -37,12 +29,11 @@ public interface IOpenApiReferenceHolder : IOpenApiSerializable /// /// Indicates if object is populated with data or is just a reference to the data /// - bool UnresolvedReference { get; set; } - //TODO the UnresolvedReference property setter should be removed and a default implementation that checks whether the target is null for the getter should be provided instead + bool UnresolvedReference { get; } /// /// Reference object. /// - OpenApiReference Reference { get; set; } + OpenApiReference Reference { get; init; } } } diff --git a/src/Microsoft.OpenApi/Interfaces/IShallowCopyable.cs b/src/Microsoft.OpenApi/Interfaces/IShallowCopyable.cs new file mode 100644 index 000000000..c1327bf0f --- /dev/null +++ b/src/Microsoft.OpenApi/Interfaces/IShallowCopyable.cs @@ -0,0 +1,12 @@ +namespace Microsoft.OpenApi.Interfaces; +/// +/// Interface for shallow copyable objects. +/// +/// The type of the resulting object +public interface IShallowCopyable +{ + /// + /// Create a shallow copy of the current instance. + /// + T CreateShallowCopy(); +} diff --git a/src/Microsoft.OpenApi/IsExternalInit.cs b/src/Microsoft.OpenApi/IsExternalInit.cs new file mode 100644 index 000000000..9c8e2ad1a --- /dev/null +++ b/src/Microsoft.OpenApi/IsExternalInit.cs @@ -0,0 +1,13 @@ +//TODO remove this if we ever remove the netstandard2.0 target +#if !NET5_0_OR_GREATER +namespace System.Runtime.CompilerServices { + using System.ComponentModel; + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit { + } +} +#endif diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index 46cb80f08..6a402478f 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -3,7 +3,6 @@ netstandard2.0;net8.0 Latest true - 2.0.0-preview5 .NET models with JSON and YAML writers for OpenAPI specification true true diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiCallback.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiCallback.cs index e4e948c1b..a8a818d33 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiCallback.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiCallback.cs @@ -9,7 +9,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the callback object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiCallback : IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiCallback : IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable { /// /// A Path Item Object used to define a callback request and expected responses. diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs index ca035cc51..3deee3d3c 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs @@ -13,3 +13,15 @@ public interface IOpenApiDescribedElement : IOpenApiElement /// public string Description { get; set; } } + +/// +/// Describes an element that has a description. +/// +public interface IOpenApiReadOnlyDescribedElement : IOpenApiElement +{ + /// + /// Long description for the example. + /// CommonMark syntax MAY be used for rich text representation. + /// + public string Description { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs index bc7639c04..ece8b48ad 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs @@ -7,7 +7,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the example object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiExample : IOpenApiDescribedElement, IOpenApiSummarizedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiExample : IOpenApiDescribedElement, IOpenApiSummarizedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable { /// /// Embedded literal example. The value field and externalValue field are mutually diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs index 9931775c7..35b6cdfe9 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs @@ -9,7 +9,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the headers object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable { /// /// Determines whether this header is mandatory. @@ -45,7 +45,7 @@ public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiSerializable /// /// The schema defining the type used for the request body. /// - public OpenApiSchema Schema { get; } + public IOpenApiSchema Schema { get; } /// /// Example of the media type. diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiLink.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiLink.cs index 854c945f8..66e8b5e3b 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiLink.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiLink.cs @@ -7,7 +7,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the link object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiLink : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiLink : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable { /// /// A relative or absolute reference to an OAS operation. diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs index 363cc1cd4..465078e43 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs @@ -8,7 +8,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the parameter object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable { /// /// REQUIRED. The name of the parameter. Parameter names are case sensitive. @@ -72,7 +72,7 @@ public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiSerializa /// /// The schema defining the type used for the parameter. /// - public OpenApiSchema Schema { get; } + public IOpenApiSchema Schema { get; } /// /// Examples of the media type. Each example SHOULD contain a value diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiPathItem.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiPathItem.cs index 41b8ab0e6..bbc316a14 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiPathItem.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiPathItem.cs @@ -8,7 +8,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the path item object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiPathItem : IOpenApiDescribedElement, IOpenApiSummarizedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiPathItem : IOpenApiDescribedElement, IOpenApiSummarizedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable { /// /// Gets the definition of operations on this path. diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs index f014d2b4d..84afff156 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs @@ -8,7 +8,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the request body object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable { /// /// Determines if the request body is required in the request. Defaults to false. diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs index 5a1f33e7a..3df66eec0 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs @@ -7,7 +7,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the response object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable { /// /// Maps a header name to its definition. diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs new file mode 100644 index 000000000..9ff8e8389 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSchema.cs @@ -0,0 +1,302 @@ +using System.Collections.Generic; +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the schema object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiSchema : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + + /// + /// Follow JSON Schema definition. Short text providing information about the data. + /// + public string Title { get; } + + /// + /// $schema, a JSON Schema dialect identifier. Value must be a URI + /// + public string Schema { get; } + + /// + /// $id - Identifies a schema resource with its canonical URI. + /// + public string Id { get; } + + /// + /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema. + /// + public string Comment { get; } + + /// + /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema. + /// + public IDictionary Vocabulary { get; } + + /// + /// $dynamicRef - an applicator that allows for deferring the full resolution until runtime, at which point it is resolved each time it is encountered while evaluating an instance + /// + public string DynamicRef { get; } + + /// + /// $dynamicAnchor - used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing. + /// + public string DynamicAnchor { get; } + + /// + /// $defs - reserves a location for schema authors to inline re-usable JSON Schemas into a more general schema. + /// The keyword does not directly affect the validation result + /// + public IDictionary Definitions { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? V31ExclusiveMaximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? V31ExclusiveMinimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool UnEvaluatedProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value MUST be a string in V2 and V3. + /// + public JsonSchemaType? Type { get; } + + /// + /// Follow JSON Schema definition: https://json-schema.org/draft/2020-12/json-schema-validation + /// + public string Const { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// While relying on JSON Schema's defined formats, + /// the OAS offers a few additional predefined formats. + /// + public string Format { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? Maximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? ExclusiveMaximum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? Minimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? ExclusiveMinimum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxLength { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinLength { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect + /// + public string Pattern { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public decimal? MultipleOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. + /// Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. + /// For example, if type is string, then default can be "foo" but cannot be 1. + /// + public JsonNode Default { get; } + + /// + /// Relevant only for Schema "properties" definitions. Declares the property as "read only". + /// This means that it MAY be sent as part of a response but SHOULD NOT be sent as part of the request. + /// If the property is marked as readOnly being true and is in the required list, + /// the required will take effect on the response only. + /// A property MUST NOT be marked as both readOnly and writeOnly being true. + /// Default value is false. + /// + public bool ReadOnly { get; } + + /// + /// Relevant only for Schema "properties" definitions. Declares the property as "write only". + /// Therefore, it MAY be sent as part of a request but SHOULD NOT be sent as part of the response. + /// If the property is marked as writeOnly being true and is in the required list, + /// the required will take effect on the request only. + /// A property MUST NOT be marked as both readOnly and writeOnly being true. + /// Default value is false. + /// + public bool WriteOnly { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList AllOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList OneOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IList AnyOf { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. + /// + public IOpenApiSchema Not { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public ISet Required { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value MUST be an object and not an array. Inline or referenced schema MUST be of a Schema Object + /// and not a standard JSON Schema. items MUST be present if the type is array. + /// + public IOpenApiSchema Items { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool? UniqueItems { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Property definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced). + /// + public IDictionary Properties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// PatternProperty definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced) + /// Each property name of this object SHOULD be a valid regular expression according to the ECMA 262 r + /// egular expression dialect. Each property value of this object MUST be an object, and each object MUST + /// be a valid Schema Object not a standard JSON Schema. + /// + public IDictionary PatternProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MaxProperties { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public int? MinProperties { get; } + + /// + /// Indicates if the schema can contain properties other than those defined by the properties map. + /// + public bool AdditionalPropertiesAllowed { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// Value can be boolean or object. Inline or referenced schema + /// MUST be of a Schema Object and not a standard JSON Schema. + /// + public IOpenApiSchema AdditionalProperties { get; } + + /// + /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate + /// between other schemas which may satisfy the payload description. + /// + public OpenApiDiscriminator Discriminator { get; } + + /// + /// A free-form property to include an example of an instance for this schema. + /// To represent examples that cannot be naturally represented in JSON or YAML, + /// a string value can be used to contain the example with escaping where necessary. + /// + public JsonNode Example { get; } + + /// + /// A free-form property to include examples of an instance for this schema. + /// To represent examples that cannot be naturally represented in JSON or YAML, + /// a list of values can be used to contain the examples with escaping where necessary. + /// + public IList Examples { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public IList Enum { get; } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + public bool UnevaluatedProperties { get; } + + /// + /// Additional external documentation for this schema. + /// + public OpenApiExternalDocs ExternalDocs { get; } + + /// + /// Specifies that a schema is deprecated and SHOULD be transitioned out of usage. + /// Default value is false. + /// + public bool Deprecated { get; } + + /// + /// This MAY be used only on properties schemas. It has no effect on root schemas. + /// Adds additional metadata to describe the XML representation of this property. + /// + public OpenApiXml Xml { get; } + + /// + /// This object stores any unrecognized keywords found in the schema. + /// + public IDictionary UnrecognizedKeywords { get; } + + /// + /// Any annotation to attach to the schema to be used by the application. + /// Annotations are NOT (de)serialized with the schema and can be used for custom properties. + /// + public IDictionary Annotations { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSecurityScheme.cs new file mode 100644 index 000000000..9580a3dad --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSecurityScheme.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the security scheme object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiSecurityScheme : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible, IShallowCopyable +{ + /// + /// REQUIRED. The type of the security scheme. Valid values are "apiKey", "http", "oauth2", "openIdConnect". + /// + public SecuritySchemeType? Type { get; } + + /// + /// REQUIRED. The name of the header, query or cookie parameter to be used. + /// + public string Name { get; } + + /// + /// REQUIRED. The location of the API key. Valid values are "query", "header" or "cookie". + /// + public ParameterLocation? In { get; } + + /// + /// REQUIRED. The name of the HTTP Authorization scheme to be used + /// in the Authorization header as defined in RFC7235. + /// + public string Scheme { get; } + + /// + /// A hint to the client to identify how the bearer token is formatted. + /// Bearer tokens are usually generated by an authorization server, + /// so this information is primarily for documentation purposes. + /// + public string BearerFormat { get; } + + /// + /// REQUIRED. An object containing configuration information for the flow types supported. + /// + public OpenApiOAuthFlows Flows { get; } + + /// + /// REQUIRED. OpenId Connect URL to discover OAuth2 configuration values. + /// + public Uri OpenIdConnectUrl { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiTag.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiTag.cs new file mode 100644 index 000000000..c2a6d8523 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiTag.cs @@ -0,0 +1,20 @@ +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the path item object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiTag : IOpenApiSerializable, IOpenApiReadOnlyExtensible, IOpenApiReadOnlyDescribedElement, IShallowCopyable +{ + /// + /// The name of the tag. + /// + public string Name { get; } + + /// + /// Additional external documentation for this tag. + /// + public OpenApiExternalDocs ExternalDocs { get; } +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs index 7f06ca277..96f5c5cf4 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiCallback.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiCallback.cs @@ -33,8 +33,9 @@ public OpenApiCallback() { } /// /// Initializes a copy of an object /// - public OpenApiCallback(IOpenApiCallback callback) + internal OpenApiCallback(IOpenApiCallback callback) { + Utils.CheckArgumentNull(callback); PathItems = callback?.PathItems != null ? new(callback?.PathItems) : null; Extensions = callback?.Extensions != null ? new Dictionary(callback.Extensions) : null; } @@ -98,5 +99,11 @@ public void SerializeAsV2(IOpenApiWriter writer) { // Callback object does not exist in V2. } + + /// + public IOpenApiCallback CreateShallowCopy() + { + return new OpenApiCallback(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index 6d65ef7b1..250254212 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -18,9 +18,9 @@ namespace Microsoft.OpenApi.Models public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible { /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public IDictionary? Schemas { get; set; } = new Dictionary(); + public IDictionary? Schemas { get; set; } = new Dictionary(); /// /// An object to hold reusable Objects. @@ -50,10 +50,10 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible public IDictionary? Headers { get; set; } = new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public IDictionary? SecuritySchemes { get; set; } = - new Dictionary(); + public IDictionary? SecuritySchemes { get; set; } = + new Dictionary(); /// /// An object to hold reusable Objects. @@ -85,13 +85,13 @@ public OpenApiComponents() { } /// public OpenApiComponents(OpenApiComponents? components) { - Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null; + Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null; Responses = components?.Responses != null ? new Dictionary(components.Responses) : null; Parameters = components?.Parameters != null ? new Dictionary(components.Parameters) : null; Examples = components?.Examples != null ? new Dictionary(components.Examples) : null; RequestBodies = components?.RequestBodies != null ? new Dictionary(components.RequestBodies) : null; Headers = components?.Headers != null ? new Dictionary(components.Headers) : null; - SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary(components.SecuritySchemes) : null; + SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary(components.SecuritySchemes) : null; Links = components?.Links != null ? new Dictionary(components.Links) : null; Callbacks = components?.Callbacks != null ? new Dictionary(components.Callbacks) : null; PathItems = components?.PathItems != null ? new Dictionary(components.PathItems) : null; diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 32afbdf90..7820a6f8e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -26,6 +26,13 @@ namespace Microsoft.OpenApi.Models /// public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenApiAnnotatable { + /// + /// Register components in the document to the workspace + /// + public void RegisterComponents() + { + Workspace?.RegisterComponents(this); + } /// /// Related workspace containing components that are referenced in a document /// @@ -239,10 +246,10 @@ public void SerializeAsV2(IOpenApiWriter writer) { var loops = writer.GetSettings().LoopDetector.Loops; - if (loops.TryGetValue(typeof(OpenApiSchema), out var schemas)) + if (loops.TryGetValue(typeof(IOpenApiSchema), out var schemas)) { - var openApiSchemas = schemas.Cast().Distinct().ToList() - .ToDictionary(k => k.Reference.Id); + var openApiSchemas = schemas.Cast().Distinct().OfType() + .ToDictionary(k => k.Reference.Id, v => v); foreach (var schema in openApiSchemas.Values.ToList()) { @@ -389,7 +396,7 @@ private static void WriteHostInfoV2(IOpenApiWriter writer, IList? else { var relativeUrl = firstServerUrl.OriginalString; - if (relativeUrl.StartsWith("//")) + if (relativeUrl.StartsWith("//", StringComparison.OrdinalIgnoreCase)) { var pathPosition = relativeUrl.IndexOf('/', 3); writer.WriteProperty(OpenApiConstants.Host, relativeUrl.Substring(0, pathPosition)); @@ -587,44 +594,44 @@ public bool AddComponent(string id, T componentToRegister) Components ??= new(); switch (componentToRegister) { - case OpenApiSchema openApiSchema: - Components.Schemas ??= new Dictionary(); + case IOpenApiSchema openApiSchema: + Components.Schemas ??= new Dictionary(); Components.Schemas.Add(id, openApiSchema); break; - case OpenApiParameter openApiParameter: + case IOpenApiParameter openApiParameter: Components.Parameters ??= new Dictionary(); Components.Parameters.Add(id, openApiParameter); break; - case OpenApiResponse openApiResponse: + case IOpenApiResponse openApiResponse: Components.Responses ??= new Dictionary(); Components.Responses.Add(id, openApiResponse); break; - case OpenApiRequestBody openApiRequestBody: + case IOpenApiRequestBody openApiRequestBody: Components.RequestBodies ??= new Dictionary(); Components.RequestBodies.Add(id, openApiRequestBody); break; - case OpenApiLink openApiLink: + case IOpenApiLink openApiLink: Components.Links ??= new Dictionary(); Components.Links.Add(id, openApiLink); break; - case OpenApiCallback openApiCallback: + case IOpenApiCallback openApiCallback: Components.Callbacks ??= new Dictionary(); Components.Callbacks.Add(id, openApiCallback); break; - case OpenApiPathItem openApiPathItem: + case IOpenApiPathItem openApiPathItem: Components.PathItems ??= new Dictionary(); Components.PathItems.Add(id, openApiPathItem); break; - case OpenApiExample openApiExample: + case IOpenApiExample openApiExample: Components.Examples ??= new Dictionary(); Components.Examples.Add(id, openApiExample); break; - case OpenApiHeader openApiHeader: + case IOpenApiHeader openApiHeader: Components.Headers ??= new Dictionary(); Components.Headers.Add(id, openApiHeader); break; - case OpenApiSecurityScheme openApiSecurityScheme: - Components.SecuritySchemes ??= new Dictionary(); + case IOpenApiSecurityScheme openApiSecurityScheme: + Components.SecuritySchemes ??= new Dictionary(); Components.SecuritySchemes.Add(id, openApiSecurityScheme); break; default: @@ -636,9 +643,9 @@ public bool AddComponent(string id, T componentToRegister) internal class FindSchemaReferences : OpenApiVisitorBase { - private Dictionary Schemas = new(); + private Dictionary Schemas = new(StringComparer.Ordinal); - public static void ResolveSchemas(OpenApiComponents? components, Dictionary schemas) + public static void ResolveSchemas(OpenApiComponents? components, Dictionary schemas) { var visitor = new FindSchemaReferences(); visitor.Schemas = schemas; @@ -651,7 +658,7 @@ public override void Visit(IOpenApiReferenceHolder referenceHolder) { switch (referenceHolder) { - case OpenApiSchema schema: + case OpenApiSchemaReference schema: if (!Schemas.ContainsKey(schema.Reference.Id)) { Schemas.Add(schema.Reference.Id, schema); @@ -664,12 +671,12 @@ public override void Visit(IOpenApiReferenceHolder referenceHolder) base.Visit(referenceHolder); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { // This is needed to handle schemas used in Responses in components - if (schema.Reference != null && !Schemas.ContainsKey(schema.Reference.Id)) + if (schema is OpenApiSchemaReference {Reference: not null} schemaReference && !Schemas.ContainsKey(schemaReference.Reference.Id)) { - Schemas.Add(schema.Reference.Id, schema); + Schemas.Add(schemaReference.Reference.Id, schema); } base.Visit(schema); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiExample.cs b/src/Microsoft.OpenApi/Models/OpenApiExample.cs index be543c525..bdfd42f4e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExample.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExample.cs @@ -39,7 +39,7 @@ public OpenApiExample() { } /// Initializes a copy of object /// /// The object - public OpenApiExample(IOpenApiExample example) + internal OpenApiExample(IOpenApiExample example) { Utils.CheckArgumentNull(example); Summary = example.Summary ?? Summary; @@ -90,5 +90,11 @@ public void SerializeAsV2(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi2_0); } + + /// + public IOpenApiExample CreateShallowCopy() + { + return new OpenApiExample(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index 1f382220b..dd7a0ec84 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -40,7 +41,7 @@ public class OpenApiHeader : IOpenApiHeader, IOpenApiReferenceable, IOpenApiExte public bool AllowReserved { get; set; } /// - public OpenApiSchema Schema { get; set; } + public IOpenApiSchema Schema { get; set; } /// public JsonNode Example { get; set; } @@ -62,20 +63,21 @@ public OpenApiHeader() { } /// /// Initializes a copy of an object /// - public OpenApiHeader(IOpenApiHeader header) + internal OpenApiHeader(IOpenApiHeader header) { - Description = header?.Description ?? Description; - Required = header?.Required ?? Required; - Deprecated = header?.Deprecated ?? Deprecated; - AllowEmptyValue = header?.AllowEmptyValue ?? AllowEmptyValue; - Style = header?.Style ?? Style; - Explode = header?.Explode ?? Explode; - AllowReserved = header?.AllowReserved ?? AllowReserved; - Schema = header?.Schema != null ? new(header.Schema) : null; - Example = header?.Example != null ? JsonNodeCloneHelper.Clone(header.Example) : null; - Examples = header?.Examples != null ? new Dictionary(header.Examples) : null; - Content = header?.Content != null ? new Dictionary(header.Content) : null; - Extensions = header?.Extensions != null ? new Dictionary(header.Extensions) : null; + Utils.CheckArgumentNull(header); + Description = header.Description ?? Description; + Required = header.Required; + Deprecated = header.Deprecated; + AllowEmptyValue = header.AllowEmptyValue; + Style = header.Style ?? Style; + Explode = header.Explode; + AllowReserved = header.AllowReserved; + Schema = header.Schema.CreateShallowCopy(); + Example = header.Example != null ? JsonNodeCloneHelper.Clone(header.Example) : null; + Examples = header.Examples != null ? new Dictionary(header.Examples) : null; + Content = header.Content != null ? new Dictionary(header.Content) : null; + Extensions = header.Extensions != null ? new Dictionary(header.Extensions) : null; } /// @@ -171,7 +173,12 @@ public void SerializeAsV2(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // schema - Schema.WriteAsItemsProperties(writer); + var targetSchema = Schema switch { + OpenApiSchemaReference schemaReference => schemaReference.Target, + OpenApiSchema schema => schema, + _ => null, + }; + targetSchema?.WriteAsItemsProperties(writer); // example writer.WriteOptionalObject(OpenApiConstants.Example, Example, (w, s) => w.WriteAny(s)); @@ -181,5 +188,11 @@ public void SerializeAsV2(IOpenApiWriter writer) writer.WriteEndObject(); } + + /// + public IOpenApiHeader CreateShallowCopy() + { + return new OpenApiHeader(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiLink.cs b/src/Microsoft.OpenApi/Models/OpenApiLink.cs index fec27dd67..09883b4a2 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiLink.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiLink.cs @@ -43,7 +43,7 @@ public OpenApiLink() { } /// /// Initializes a copy of an object /// - public OpenApiLink(IOpenApiLink link) + internal OpenApiLink(IOpenApiLink link) { Utils.CheckArgumentNull(link); OperationRef = link.OperationRef ?? OperationRef; @@ -102,5 +102,11 @@ public void SerializeAsV2(IOpenApiWriter writer) { // Link object does not exist in V2. } + + /// + public IOpenApiLink CreateShallowCopy() + { + return new OpenApiLink(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs index 23acd0de9..7ba469bc6 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiMediaType.cs @@ -19,16 +19,10 @@ namespace Microsoft.OpenApi.Models /// public class OpenApiMediaType : IOpenApiSerializable, IOpenApiExtensible { - private OpenApiSchema? _schema; - /// /// The schema defining the type used for the request body. /// - public virtual OpenApiSchema? Schema - { - get => _schema; - set => _schema = value; - } + public IOpenApiSchema? Schema { get; set; } /// /// Example of the media type. @@ -65,7 +59,7 @@ public OpenApiMediaType() { } /// public OpenApiMediaType(OpenApiMediaType? mediaType) { - _schema = mediaType?.Schema != null ? new(mediaType.Schema) : null; + Schema = mediaType?.Schema?.CreateShallowCopy(); Example = mediaType?.Example != null ? JsonNodeCloneHelper.Clone(mediaType.Example) : null; Examples = mediaType?.Examples != null ? new Dictionary(mediaType.Examples) : null; Encoding = mediaType?.Encoding != null ? new Dictionary(mediaType.Encoding) : null; @@ -94,7 +88,7 @@ public void SerializeAsV3(IOpenApiWriter writer) private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); writer.WriteStartObject(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs index a3ded96eb..3acbd05ab 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs @@ -120,22 +120,23 @@ public OpenApiOperation() { } /// /// Initializes a copy of an object /// - public OpenApiOperation(OpenApiOperation? operation) + public OpenApiOperation(OpenApiOperation operation) { - Tags = operation?.Tags != null ? new List(operation.Tags) : null; - Summary = operation?.Summary ?? Summary; - Description = operation?.Description ?? Description; - ExternalDocs = operation?.ExternalDocs != null ? new(operation?.ExternalDocs) : null; - OperationId = operation?.OperationId ?? OperationId; - Parameters = operation?.Parameters != null ? new List(operation.Parameters) : null; - RequestBody = operation?.RequestBody != null ? new OpenApiRequestBody(operation?.RequestBody) : null; - Responses = operation?.Responses != null ? new(operation?.Responses) : null; - Callbacks = operation?.Callbacks != null ? new Dictionary(operation.Callbacks) : null; - Deprecated = operation?.Deprecated ?? Deprecated; - Security = operation?.Security != null ? new List(operation.Security) : null; - Servers = operation?.Servers != null ? new List(operation.Servers) : null; - Extensions = operation?.Extensions != null ? new Dictionary(operation.Extensions) : null; - Annotations = operation?.Annotations != null ? new Dictionary(operation.Annotations) : null; + Utils.CheckArgumentNull(operation); + Tags = operation.Tags != null ? new List(operation.Tags) : null; + Summary = operation.Summary ?? Summary; + Description = operation.Description ?? Description; + ExternalDocs = operation.ExternalDocs != null ? new(operation.ExternalDocs) : null; + OperationId = operation.OperationId ?? OperationId; + Parameters = operation.Parameters != null ? new List(operation.Parameters) : null; + RequestBody = operation.RequestBody?.CreateShallowCopy(); + Responses = operation.Responses != null ? new(operation.Responses) : null; + Callbacks = operation.Callbacks != null ? new Dictionary(operation.Callbacks) : null; + Deprecated = operation.Deprecated; + Security = operation.Security != null ? new List(operation.Security) : null; + Servers = operation.Servers != null ? new List(operation.Servers) : null; + Extensions = operation.Extensions != null ? new Dictionary(operation.Extensions) : null; + Annotations = operation.Annotations != null ? new Dictionary(operation.Annotations) : null; } /// @@ -159,7 +160,7 @@ public void SerializeAsV3(IOpenApiWriter writer) /// private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); writer.WriteStartObject(); @@ -277,12 +278,7 @@ public void SerializeAsV2(IOpenApiWriter writer) var produces = Responses .Where(static r => r.Value.Content != null) .SelectMany(static r => r.Value.Content?.Keys ?? []) - .Concat( - Responses - .Select(static r => r.Value) - .OfType() - .Where(static r => r.Reference is {HostDocument: not null}) - .SelectMany(static r => r.Content?.Keys ?? [])) + .Where(static m => !string.IsNullOrEmpty(m)) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index 87a761c8b..0f1d7c03a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -9,6 +9,7 @@ using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -57,7 +58,7 @@ public bool Explode public bool AllowReserved { get; set; } /// - public OpenApiSchema Schema { get; set; } + public IOpenApiSchema Schema { get; set; } /// public IDictionary Examples { get; set; } = new Dictionary(); @@ -79,7 +80,7 @@ public OpenApiParameter() { } /// /// Initializes a clone instance of object /// - public OpenApiParameter(IOpenApiParameter parameter) + internal OpenApiParameter(IOpenApiParameter parameter) { Utils.CheckArgumentNull(parameter); Name = parameter.Name ?? Name; @@ -89,7 +90,7 @@ public OpenApiParameter(IOpenApiParameter parameter) Style = parameter.Style ?? Style; Explode = parameter.Explode; AllowReserved = parameter.AllowReserved; - Schema = parameter.Schema != null ? new(parameter.Schema) : null; + Schema = parameter.Schema.CreateShallowCopy(); Examples = parameter.Examples != null ? new Dictionary(parameter.Examples) : null; Example = parameter.Example != null ? JsonNodeCloneHelper.Clone(parameter.Example) : null; Content = parameter.Content != null ? new Dictionary(parameter.Content) : null; @@ -207,7 +208,7 @@ public void SerializeAsV2(IOpenApiWriter writer) } // In V2 parameter's type can't be a reference to a custom object schema or can't be of type object // So in that case map the type as string. - else if (Schema?.UnresolvedReference == true || Schema?.Type == JsonSchemaType.Object) + else if (Schema is OpenApiSchemaReference { UnresolvedReference: true } || (Schema?.Type & JsonSchemaType.Object) == JsonSchemaType.Object) { writer.WriteProperty(OpenApiConstants.Type, "string"); } @@ -230,9 +231,14 @@ public void SerializeAsV2(IOpenApiWriter writer) // uniqueItems // enum // multipleOf - if (Schema != null) + var targetSchema = Schema switch { + OpenApiSchemaReference schemaReference => schemaReference.Target, + OpenApiSchema schema => schema, + _ => null, + }; + if (targetSchema is not null) { - Schema.WriteAsItemsProperties(writer); + targetSchema.WriteAsItemsProperties(writer); var extensions = Schema.Extensions; if (extensions != null) { @@ -296,6 +302,12 @@ public void SerializeAsV2(IOpenApiWriter writer) _ => (ParameterStyle?)ParameterStyle.Simple, }; } + + /// + public IOpenApiParameter CreateShallowCopy() + { + return new OpenApiParameter(this); + } } /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs index 4aa4dedb1..f3baa5743 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs @@ -52,15 +52,15 @@ public OpenApiPathItem() { } /// /// Initializes a clone of an object /// - public OpenApiPathItem(IOpenApiPathItem pathItem) + internal OpenApiPathItem(IOpenApiPathItem pathItem) { Utils.CheckArgumentNull(pathItem); - Summary = pathItem?.Summary ?? Summary; - Description = pathItem?.Description ?? Description; - Operations = pathItem?.Operations != null ? new Dictionary(pathItem.Operations) : null; - Servers = pathItem?.Servers != null ? new List(pathItem.Servers) : null; - Parameters = pathItem?.Parameters != null ? new List(pathItem.Parameters) : null; - Extensions = pathItem?.Extensions != null ? new Dictionary(pathItem.Extensions) : null; + Summary = pathItem.Summary ?? Summary; + Description = pathItem.Description ?? Description; + Operations = pathItem.Operations != null ? new Dictionary(pathItem.Operations) : null; + Servers = pathItem.Servers != null ? new List(pathItem.Servers) : null; + Parameters = pathItem.Parameters != null ? new List(pathItem.Parameters) : null; + Extensions = pathItem.Extensions != null ? new Dictionary(pathItem.Extensions) : null; } /// @@ -151,5 +151,11 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio writer.WriteEndObject(); } + + /// + public IOpenApiPathItem CreateShallowCopy() + { + return new OpenApiPathItem(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiReference.cs b/src/Microsoft.OpenApi/Models/OpenApiReference.cs index 191f884ea..43d307fad 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiReference.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiReference.cs @@ -4,6 +4,7 @@ using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -11,7 +12,7 @@ namespace Microsoft.OpenApi.Models /// /// A simple object to allow referencing other components in the specification, internally and externally. /// - public class OpenApiReference : IOpenApiSerializable + public class OpenApiReference : IOpenApiSerializable, IOpenApiDescribedElement, IOpenApiSummarizedElement { /// /// A short summary which by default SHOULD override that of the referenced component. @@ -32,13 +33,13 @@ public class OpenApiReference : IOpenApiSerializable /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public string ExternalResource { get; set; } + public string ExternalResource { get; init; } /// /// The element type referenced. /// /// This must be present if is not present. - public ReferenceType? Type { get; set; } + public ReferenceType? Type { get; init; } /// /// The identifier of the reusable component of one particular ReferenceType. @@ -47,7 +48,7 @@ public class OpenApiReference : IOpenApiSerializable /// If ExternalResource is not present, this is the name of the component without the reference type name. /// For example, if the reference is '#/components/schemas/componentName', the Id is 'componentName'. /// - public string Id { get; set; } + public string Id { get; init; } /// /// Gets a flag indicating whether this reference is an external reference. @@ -62,12 +63,13 @@ public class OpenApiReference : IOpenApiSerializable /// /// Gets a flag indicating whether a file is a valid OpenAPI document or a fragment /// - public bool IsFragment = false; + public bool IsFragment { get; init; } + private OpenApiDocument hostDocument; /// /// The OpenApiDocument that is hosting the OpenApiReference instance. This is used to enable dereferencing the reference. /// - public OpenApiDocument HostDocument { get; set; } + public OpenApiDocument HostDocument { get => hostDocument; init => hostDocument = value; } /// /// Gets the full reference string for v3.0. @@ -95,7 +97,7 @@ public string ReferenceV3 { return Id; } - if (Id.StartsWith("http")) + if (Id.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { return Id; } @@ -145,12 +147,13 @@ public OpenApiReference() { } /// public OpenApiReference(OpenApiReference reference) { - Summary = reference?.Summary; - Description = reference?.Description; - ExternalResource = reference?.ExternalResource; - Type = reference?.Type; - Id = reference?.Id; - HostDocument = new(reference?.HostDocument); + Utils.CheckArgumentNull(reference); + Summary = reference.Summary; + Description = reference.Description; + ExternalResource = reference.ExternalResource; + Type = reference.Type; + Id = reference.Id; + HostDocument = reference.HostDocument; } /// @@ -238,7 +241,7 @@ private string GetExternalReferenceV3() return ExternalResource + "#" + Id; } - if (Id.StartsWith("http")) + if (Id.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { return Id; } @@ -276,5 +279,16 @@ private string GetReferenceTypeNameAsV2(ReferenceType type) // to indicate that the reference is not pointing to any object. }; } + + /// + /// Sets the host document after deserialization or before serialization. + /// This method is internal on purpose to avoid consumers mutating the host document. + /// + /// Host document to set if none is present + internal void EnsureHostDocumentIsSet(OpenApiDocument currentDocument) + { + Utils.CheckArgumentNull(currentDocument); + hostDocument ??= currentDocument; + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index b5fd3f605..95f86dba3 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -37,13 +38,13 @@ public OpenApiRequestBody() { } /// /// Initializes a copy instance of an object /// - public OpenApiRequestBody(IOpenApiRequestBody requestBody) + internal OpenApiRequestBody(IOpenApiRequestBody requestBody) { Utils.CheckArgumentNull(requestBody); - Description = requestBody?.Description ?? Description; - Required = requestBody?.Required ?? Required; - Content = requestBody?.Content != null ? new Dictionary(requestBody.Content) : null; - Extensions = requestBody?.Extensions != null ? new Dictionary(requestBody.Extensions) : null; + Description = requestBody.Description ?? Description; + Required = requestBody.Required; + Content = requestBody.Content != null ? new Dictionary(requestBody.Content) : null; + Extensions = requestBody.Extensions != null ? new Dictionary(requestBody.Extensions) : null; } /// @@ -123,23 +124,37 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter foreach (var property in Content.First().Value.Schema.Properties) { - var paramSchema = property.Value; + var paramSchema = property.Value.CreateShallowCopy(); if ((paramSchema.Type & JsonSchemaType.String) == JsonSchemaType.String && ("binary".Equals(paramSchema.Format, StringComparison.OrdinalIgnoreCase) || "base64".Equals(paramSchema.Format, StringComparison.OrdinalIgnoreCase))) { - paramSchema.Type = "file".ToJsonSchemaType(); - paramSchema.Format = null; + var updatedSchema = paramSchema switch { + OpenApiSchema s => s, // we already have a copy + // we have a copy of a reference but don't want to mutate the source schema + // TODO might need recursive resolution of references here + OpenApiSchemaReference r => (OpenApiSchema)r.Target.CreateShallowCopy(), + _ => throw new InvalidOperationException("Unexpected schema type") + }; + updatedSchema.Type = "file".ToJsonSchemaType(); + updatedSchema.Format = null; + paramSchema = updatedSchema; } yield return new OpenApiFormDataParameter() { - Description = property.Value.Description, + Description = paramSchema.Description, Name = property.Key, - Schema = property.Value, + Schema = paramSchema, Examples = Content.Values.FirstOrDefault()?.Examples, Required = Content.First().Value.Schema.Required?.Contains(property.Key) ?? false }; } } + + /// + public IOpenApiRequestBody CreateShallowCopy() + { + return new OpenApiRequestBody(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index cf2a54cfb..0ec6cbb84 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -38,14 +38,14 @@ public OpenApiResponse() { } /// /// Initializes a copy of object /// - public OpenApiResponse(IOpenApiResponse response) + internal OpenApiResponse(IOpenApiResponse response) { Utils.CheckArgumentNull(response); - Description = response?.Description ?? Description; - Headers = response?.Headers != null ? new Dictionary(response.Headers) : null; - Content = response?.Content != null ? new Dictionary(response.Content) : null; - Links = response?.Links != null ? new Dictionary(response.Links) : null; - Extensions = response?.Extensions != null ? new Dictionary(response.Extensions) : null; + Description = response.Description ?? Description; + Headers = response.Headers != null ? new Dictionary(response.Headers) : null; + Content = response.Content != null ? new Dictionary(response.Content) : null; + Links = response.Links != null ? new Dictionary(response.Links) : null; + Extensions = response.Extensions != null ? new Dictionary(response.Extensions) : null; } /// @@ -164,5 +164,11 @@ public void SerializeAsV2(IOpenApiWriter writer) writer.WriteEndObject(); } + + /// + public IOpenApiResponse CreateShallowCopy() + { + return new OpenApiResponse(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index ff5a8eb48..cfed33744 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -4,10 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Text.Json.Nodes; +using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Helpers; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -15,316 +18,160 @@ namespace Microsoft.OpenApi.Models /// /// The Schema Object allows the definition of input and output data types. /// - public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiReferenceable, IOpenApiReferenceHolder - {//TODO remove the implementation of IOpenAPiReferenceHolder when we have removed the inheritance from the inheritance type to this type - /// - /// Follow JSON Schema definition. Short text providing information about the data. - /// - public virtual string Title { get; set; } - - /// - /// $schema, a JSON Schema dialect identifier. Value must be a URI - /// - public virtual string Schema { get; set; } - - /// - /// $id - Identifies a schema resource with its canonical URI. - /// - public virtual string Id { get; set; } - - /// - /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema. - /// - public virtual string Comment { get; set; } + public class OpenApiSchema : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiSchema + { + /// + public string Title { get; set; } - /// - /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema. - /// - public virtual IDictionary Vocabulary { get; set; } + /// + public string Schema { get; set; } - /// - /// $dynamicRef - an applicator that allows for deferring the full resolution until runtime, at which point it is resolved each time it is encountered while evaluating an instance - /// - public virtual string DynamicRef { get; set; } + /// + public string Id { get; set; } - /// - /// $dynamicAnchor - used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing. - /// - public virtual string DynamicAnchor { get; set; } + /// + public string Comment { get; set; } - /// - /// $defs - reserves a location for schema authors to inline re-usable JSON Schemas into a more general schema. - /// The keyword does not directly affect the validation result - /// - public virtual IDictionary Definitions { get; set; } + /// + public IDictionary Vocabulary { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? V31ExclusiveMaximum { get; set; } + /// + public string DynamicRef { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? V31ExclusiveMinimum { get; set; } + /// + public string DynamicAnchor { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool UnEvaluatedProperties { get; set; } + /// + public IDictionary Definitions { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value MUST be a string in V2 and V3. - /// - public virtual JsonSchemaType? Type { get; set; } + /// + public decimal? V31ExclusiveMaximum { get; set; } - /// - /// Follow JSON Schema definition: https://json-schema.org/draft/2020-12/json-schema-validation - /// - public virtual string Const { get; set; } + /// + public decimal? V31ExclusiveMinimum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// While relying on JSON Schema's defined formats, - /// the OAS offers a few additional predefined formats. - /// - public virtual string Format { get; set; } + /// + public bool UnEvaluatedProperties { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } + /// + public JsonSchemaType? Type { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? Maximum { get; set; } + /// + public string Const { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? ExclusiveMaximum { get; set; } + /// + public string Format { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? Minimum { get; set; } + /// + public string Description { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? ExclusiveMinimum { get; set; } + /// + public decimal? Maximum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxLength { get; set; } + /// + public bool? ExclusiveMaximum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinLength { get; set; } + /// + public decimal? Minimum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect - /// - public virtual string Pattern { get; set; } + /// + public bool? ExclusiveMinimum { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual decimal? MultipleOf { get; set; } + /// + public int? MaxLength { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. - /// Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. - /// For example, if type is string, then default can be "foo" but cannot be 1. - /// - public virtual JsonNode Default { get; set; } + /// + public int? MinLength { get; set; } - /// - /// Relevant only for Schema "properties" definitions. Declares the property as "read only". - /// This means that it MAY be sent as part of a response but SHOULD NOT be sent as part of the request. - /// If the property is marked as readOnly being true and is in the required list, - /// the required will take effect on the response only. - /// A property MUST NOT be marked as both readOnly and writeOnly being true. - /// Default value is false. - /// - public virtual bool ReadOnly { get; set; } + /// + public string Pattern { get; set; } - /// - /// Relevant only for Schema "properties" definitions. Declares the property as "write only". - /// Therefore, it MAY be sent as part of a request but SHOULD NOT be sent as part of the response. - /// If the property is marked as writeOnly being true and is in the required list, - /// the required will take effect on the request only. - /// A property MUST NOT be marked as both readOnly and writeOnly being true. - /// Default value is false. - /// - public virtual bool WriteOnly { get; set; } + /// + public decimal? MultipleOf { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList AllOf { get; set; } = new List(); + /// + public JsonNode Default { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList OneOf { get; set; } = new List(); + /// + public bool ReadOnly { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual IList AnyOf { get; set; } = new List(); + /// + public bool WriteOnly { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual OpenApiSchema Not { get; set; } + /// + public IList AllOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual ISet Required { get; set; } = new HashSet(); + /// + public IList OneOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value MUST be an object and not an array. Inline or referenced schema MUST be of a Schema Object - /// and not a standard JSON Schema. items MUST be present if the type is array. - /// - public virtual OpenApiSchema Items { get; set; } + /// + public IList AnyOf { get; set; } = []; - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxItems { get; set; } + /// + public IOpenApiSchema Not { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinItems { get; set; } + /// + public ISet Required { get; set; } = new HashSet(); - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool? UniqueItems { get; set; } + /// + public IOpenApiSchema Items { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Property definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced). - /// - public virtual IDictionary Properties { get; set; } = new Dictionary(); + /// + public int? MaxItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// PatternProperty definitions MUST be a Schema Object and not a standard JSON Schema (inline or referenced) - /// Each property name of this object SHOULD be a valid regular expression according to the ECMA 262 r - /// egular expression dialect. Each property value of this object MUST be an object, and each object MUST - /// be a valid Schema Object not a standard JSON Schema. - /// - public virtual IDictionary PatternProperties { get; set; } = new Dictionary(); + /// + public int? MinItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MaxProperties { get; set; } + /// + public bool? UniqueItems { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual int? MinProperties { get; set; } + /// + public IDictionary Properties { get; set; } = new Dictionary(StringComparer.Ordinal); - /// - /// Indicates if the schema can contain properties other than those defined by the properties map. - /// - public virtual bool AdditionalPropertiesAllowed { get; set; } = true; + /// + public IDictionary PatternProperties { get; set; } = new Dictionary(StringComparer.Ordinal); - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// Value can be boolean or object. Inline or referenced schema - /// MUST be of a Schema Object and not a standard JSON Schema. - /// - public virtual OpenApiSchema AdditionalProperties { get; set; } + /// + public int? MaxProperties { get; set; } - /// - /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate - /// between other schemas which may satisfy the payload description. - /// - public virtual OpenApiDiscriminator Discriminator { get; set; } + /// + public int? MinProperties { get; set; } - /// - /// A free-form property to include an example of an instance for this schema. - /// To represent examples that cannot be naturally represented in JSON or YAML, - /// a string value can be used to contain the example with escaping where necessary. - /// - public virtual JsonNode Example { get; set; } + /// + public bool AdditionalPropertiesAllowed { get; set; } = true; - /// - /// A free-form property to include examples of an instance for this schema. - /// To represent examples that cannot be naturally represented in JSON or YAML, - /// a list of values can be used to contain the examples with escaping where necessary. - /// - public virtual IList Examples { get; set; } + /// + public IOpenApiSchema AdditionalProperties { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual IList Enum { get; set; } = new List(); + /// + public OpenApiDiscriminator Discriminator { get; set; } - /// - /// Allows sending a null value for the defined schema. Default value is false. - /// - public virtual bool Nullable { get; set; } + /// + public JsonNode Example { get; set; } - /// - /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 - /// - public virtual bool UnevaluatedProperties { get; set;} + /// + public IList Examples { get; set; } - /// - /// Additional external documentation for this schema. - /// - public virtual OpenApiExternalDocs ExternalDocs { get; set; } + /// + public IList Enum { get; set; } = new List(); - /// - /// Specifies that a schema is deprecated and SHOULD be transitioned out of usage. - /// Default value is false. - /// - public virtual bool Deprecated { get; set; } + /// + public bool UnevaluatedProperties { get; set;} - /// - /// This MAY be used only on properties schemas. It has no effect on root schemas. - /// Adds additional metadata to describe the XML representation of this property. - /// - public virtual OpenApiXml Xml { get; set; } + /// + public OpenApiExternalDocs ExternalDocs { get; set; } - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public bool Deprecated { get; set; } - /// - /// This object stores any unrecognized keywords found in the schema. - /// - public virtual IDictionary UnrecognizedKeywords { get; set; } = new Dictionary(); + /// + public OpenApiXml Xml { get; set; } - /// - /// Indicates object is a placeholder reference to an actual object and does not contain valid data. - /// - public virtual bool UnresolvedReference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); - /// - /// Reference object. - /// - public virtual OpenApiReference Reference { get; set; } + /// + public IDictionary UnrecognizedKeywords { get; set; } = new Dictionary(); /// public IDictionary Annotations { get; set; } @@ -335,78 +182,73 @@ public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiRe public OpenApiSchema() { } /// - /// Initializes a copy of object + /// Initializes a copy of object /// - public OpenApiSchema(OpenApiSchema schema) + /// The schema object to copy from. + internal OpenApiSchema(IOpenApiSchema schema) { - Title = schema?.Title ?? Title; - Id = schema?.Id ?? Id; - Const = schema?.Const ?? Const; - Schema = schema?.Schema ?? Schema; - Comment = schema?.Comment ?? Comment; - Vocabulary = schema?.Vocabulary != null ? new Dictionary(schema.Vocabulary) : null; - DynamicAnchor = schema?.DynamicAnchor ?? DynamicAnchor; - DynamicRef = schema?.DynamicRef ?? DynamicRef; - Definitions = schema?.Definitions != null ? new Dictionary(schema.Definitions) : null; - UnevaluatedProperties = schema?.UnevaluatedProperties ?? UnevaluatedProperties; - V31ExclusiveMaximum = schema?.V31ExclusiveMaximum ?? V31ExclusiveMaximum; - V31ExclusiveMinimum = schema?.V31ExclusiveMinimum ?? V31ExclusiveMinimum; - Type = schema?.Type ?? Type; - Format = schema?.Format ?? Format; - Description = schema?.Description ?? Description; - Maximum = schema?.Maximum ?? Maximum; - ExclusiveMaximum = schema?.ExclusiveMaximum ?? ExclusiveMaximum; - Minimum = schema?.Minimum ?? Minimum; - ExclusiveMinimum = schema?.ExclusiveMinimum ?? ExclusiveMinimum; - MaxLength = schema?.MaxLength ?? MaxLength; - MinLength = schema?.MinLength ?? MinLength; - Pattern = schema?.Pattern ?? Pattern; - MultipleOf = schema?.MultipleOf ?? MultipleOf; - Default = schema?.Default != null ? JsonNodeCloneHelper.Clone(schema?.Default) : null; - ReadOnly = schema?.ReadOnly ?? ReadOnly; - WriteOnly = schema?.WriteOnly ?? WriteOnly; - AllOf = schema?.AllOf != null ? new List(schema.AllOf) : null; - OneOf = schema?.OneOf != null ? new List(schema.OneOf) : null; - AnyOf = schema?.AnyOf != null ? new List(schema.AnyOf) : null; - Not = schema?.Not != null ? new(schema?.Not) : null; - Required = schema?.Required != null ? new HashSet(schema.Required) : null; - Items = schema?.Items != null ? new(schema?.Items) : null; - MaxItems = schema?.MaxItems ?? MaxItems; - MinItems = schema?.MinItems ?? MinItems; - UniqueItems = schema?.UniqueItems ?? UniqueItems; - Properties = schema?.Properties != null ? new Dictionary(schema.Properties) : null; - PatternProperties = schema?.PatternProperties != null ? new Dictionary(schema.PatternProperties) : null; - MaxProperties = schema?.MaxProperties ?? MaxProperties; - MinProperties = schema?.MinProperties ?? MinProperties; - AdditionalPropertiesAllowed = schema?.AdditionalPropertiesAllowed ?? AdditionalPropertiesAllowed; - AdditionalProperties = schema?.AdditionalProperties != null ? new(schema?.AdditionalProperties) : null; - Discriminator = schema?.Discriminator != null ? new(schema?.Discriminator) : null; - Example = schema?.Example != null ? JsonNodeCloneHelper.Clone(schema?.Example) : null; - Examples = schema?.Examples != null ? new List(schema.Examples) : null; - Enum = schema?.Enum != null ? new List(schema.Enum) : null; - Nullable = schema?.Nullable ?? Nullable; - ExternalDocs = schema?.ExternalDocs != null ? new(schema?.ExternalDocs) : null; - Deprecated = schema?.Deprecated ?? Deprecated; - Xml = schema?.Xml != null ? new(schema?.Xml) : null; - Extensions = schema?.Extensions != null ? new Dictionary(schema.Extensions) : null; - UnresolvedReference = schema?.UnresolvedReference ?? UnresolvedReference; - Reference = schema?.Reference != null ? new(schema?.Reference) : null; - Annotations = schema?.Annotations != null ? new Dictionary(schema?.Annotations) : null; - UnrecognizedKeywords = schema?.UnrecognizedKeywords != null ? new Dictionary(schema?.UnrecognizedKeywords) : null; + Utils.CheckArgumentNull(schema); + Title = schema.Title ?? Title; + Id = schema.Id ?? Id; + Const = schema.Const ?? Const; + Schema = schema.Schema ?? Schema; + Comment = schema.Comment ?? Comment; + Vocabulary = schema.Vocabulary != null ? new Dictionary(schema.Vocabulary) : null; + DynamicAnchor = schema.DynamicAnchor ?? DynamicAnchor; + DynamicRef = schema.DynamicRef ?? DynamicRef; + Definitions = schema.Definitions != null ? new Dictionary(schema.Definitions) : null; + UnevaluatedProperties = schema.UnevaluatedProperties; + V31ExclusiveMaximum = schema.V31ExclusiveMaximum ?? V31ExclusiveMaximum; + V31ExclusiveMinimum = schema.V31ExclusiveMinimum ?? V31ExclusiveMinimum; + Type = schema.Type ?? Type; + Format = schema.Format ?? Format; + Description = schema.Description ?? Description; + Maximum = schema.Maximum ?? Maximum; + ExclusiveMaximum = schema.ExclusiveMaximum ?? ExclusiveMaximum; + Minimum = schema.Minimum ?? Minimum; + ExclusiveMinimum = schema.ExclusiveMinimum ?? ExclusiveMinimum; + MaxLength = schema.MaxLength ?? MaxLength; + MinLength = schema.MinLength ?? MinLength; + Pattern = schema.Pattern ?? Pattern; + MultipleOf = schema.MultipleOf ?? MultipleOf; + Default = schema.Default != null ? JsonNodeCloneHelper.Clone(schema.Default) : null; + ReadOnly = schema.ReadOnly; + WriteOnly = schema.WriteOnly; + AllOf = schema.AllOf != null ? new List(schema.AllOf) : null; + OneOf = schema.OneOf != null ? new List(schema.OneOf) : null; + AnyOf = schema.AnyOf != null ? new List(schema.AnyOf) : null; + Not = schema.Not?.CreateShallowCopy(); + Required = schema.Required != null ? new HashSet(schema.Required) : null; + Items = schema.Items?.CreateShallowCopy(); + MaxItems = schema.MaxItems ?? MaxItems; + MinItems = schema.MinItems ?? MinItems; + UniqueItems = schema.UniqueItems ?? UniqueItems; + Properties = schema.Properties != null ? new Dictionary(schema.Properties) : null; + PatternProperties = schema.PatternProperties != null ? new Dictionary(schema.PatternProperties) : null; + MaxProperties = schema.MaxProperties ?? MaxProperties; + MinProperties = schema.MinProperties ?? MinProperties; + AdditionalPropertiesAllowed = schema.AdditionalPropertiesAllowed; + AdditionalProperties = schema.AdditionalProperties?.CreateShallowCopy(); + Discriminator = schema.Discriminator != null ? new(schema.Discriminator) : null; + Example = schema.Example != null ? JsonNodeCloneHelper.Clone(schema.Example) : null; + Examples = schema.Examples != null ? new List(schema.Examples) : null; + Enum = schema.Enum != null ? new List(schema.Enum) : null; + ExternalDocs = schema.ExternalDocs != null ? new(schema.ExternalDocs) : null; + Deprecated = schema.Deprecated; + Xml = schema.Xml != null ? new(schema.Xml) : null; + Extensions = schema.Extensions != null ? new Dictionary(schema.Extensions) : null; + Annotations = schema.Annotations != null ? new Dictionary(schema.Annotations) : null; + UnrecognizedKeywords = schema.UnrecognizedKeywords != null ? new Dictionary(schema.UnrecognizedKeywords) : null; } - /// - /// Serialize to Open Api v3.1 - /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + /// + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } - /// - /// Serialize to Open Api v3.0 - /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + /// + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } @@ -512,12 +354,6 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version // default writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d)); - // nullable - if (version is OpenApiSpecVersion.OpenApi3_0) - { - writer.WriteProperty(OpenApiConstants.Nullable, Nullable, false); - } - // discriminator writer.WriteOptionalObject(OpenApiConstants.Discriminator, Discriminator, callback); @@ -551,9 +387,8 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version writer.WriteEndObject(); } -/// - - public virtual void SerializeAsV2(IOpenApiWriter writer) + /// + public void SerializeAsV2(IOpenApiWriter writer) { SerializeAsV2(writer: writer, parentRequiredProperties: new HashSet(), propertyName: null); } @@ -578,7 +413,7 @@ internal void WriteJsonSchemaKeywords(IOpenApiWriter writer) internal void WriteAsItemsProperties(IOpenApiWriter writer) { // type - writer.WriteProperty(OpenApiConstants.Type, Type.ToIdentifier()); + writer.WriteProperty(OpenApiConstants.Type, (Type & ~JsonSchemaType.Null).ToIdentifier()); // format WriteFormatProperty(writer); @@ -654,7 +489,7 @@ private void WriteFormatProperty(IOpenApiWriter writer) /// The open api writer. /// The list of required properties in parent schema. /// The property name that will be serialized. - internal virtual void SerializeAsV2( + private void SerializeAsV2( IOpenApiWriter writer, ISet parentRequiredProperties, string propertyName) @@ -745,7 +580,12 @@ internal virtual void SerializeAsV2( // properties writer.WriteOptionalMap(OpenApiConstants.Properties, Properties, (w, key, s) => - s.SerializeAsV2(w, Required, key)); + { + if (s is OpenApiSchema oais) + oais.SerializeAsV2(w, Required, key); + else + s.SerializeAsV2(w); + }); // additionalProperties if (AdditionalPropertiesAllowed) @@ -788,20 +628,38 @@ internal virtual void SerializeAsV2( private void SerializeTypeProperty(JsonSchemaType? type, IOpenApiWriter writer, OpenApiSpecVersion version) { + // check whether nullable is true for upcasting purposes + var isNullable = (Type.HasValue && Type.Value.HasFlag(JsonSchemaType.Null)) || + Extensions is not null && + Extensions.TryGetValue(OpenApiConstants.NullableExtension, out var nullExtRawValue) && + nullExtRawValue is OpenApiAny { Node: JsonNode jsonNode} && + jsonNode.GetValueKind() is JsonValueKind.True; if (type is null) { - return; - } - if (!HasMultipleTypes(type.Value)) - { - // check whether nullable is true for upcasting purposes - if (version is OpenApiSpecVersion.OpenApi3_1 && (Nullable || Extensions.ContainsKey(OpenApiConstants.NullableExtension))) + if (version is OpenApiSpecVersion.OpenApi3_0 && isNullable) { - UpCastSchemaTypeToV31(type, writer); + writer.WriteProperty(OpenApiConstants.Nullable, true); } - else + } + else if (!HasMultipleTypes(type.Value)) + { + + switch (version) { - writer.WriteProperty(OpenApiConstants.Type, type.Value.ToIdentifier()); + case OpenApiSpecVersion.OpenApi3_1 when isNullable: + UpCastSchemaTypeToV31(type.Value, writer); + break; + case OpenApiSpecVersion.OpenApi3_0 when isNullable && type.Value == JsonSchemaType.Null: + writer.WriteProperty(OpenApiConstants.Nullable, true); + writer.WriteProperty(OpenApiConstants.Type, JsonSchemaType.Object.ToIdentifier()); + break; + case OpenApiSpecVersion.OpenApi3_0 when isNullable && type.Value != JsonSchemaType.Null: + writer.WriteProperty(OpenApiConstants.Nullable, true); + writer.WriteProperty(OpenApiConstants.Type, type.Value.ToIdentifier()); + break; + default: + writer.WriteProperty(OpenApiConstants.Type, type.Value.ToIdentifier()); + break; } } else @@ -833,14 +691,21 @@ private static bool HasMultipleTypes(JsonSchemaType schemaType) schemaTypeNumeric != (int)JsonSchemaType.Null; } - private void UpCastSchemaTypeToV31(JsonSchemaType? type, IOpenApiWriter writer) + private static void UpCastSchemaTypeToV31(JsonSchemaType type, IOpenApiWriter writer) { // create a new array and insert the type and "null" as values - Type = type | JsonSchemaType.Null; - var list = (from JsonSchemaType? flag in jsonSchemaTypeValues// Check if the flag is set in 'type' using a bitwise AND operation - where Type.Value.HasFlag(flag) + var temporaryType = type | JsonSchemaType.Null; + var list = (from JsonSchemaType flag in jsonSchemaTypeValues// Check if the flag is set in 'type' using a bitwise AND operation + where temporaryType.HasFlag(flag) select flag.ToIdentifier()).ToList(); - writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s)); + if (list.Count > 1) + { + writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s)); + } + else + { + writer.WriteProperty(OpenApiConstants.Type, list[0]); + } } #if NET5_0_OR_GREATER @@ -861,9 +726,9 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType schemaType, IOpenApiWriter ? OpenApiConstants.NullableExtension : OpenApiConstants.Nullable; - if (!HasMultipleTypes(schemaType ^ JsonSchemaType.Null) && (schemaType & JsonSchemaType.Null) == JsonSchemaType.Null) // checks for two values and one is null + if (!HasMultipleTypes(schemaType & ~JsonSchemaType.Null) && (schemaType & JsonSchemaType.Null) == JsonSchemaType.Null) // checks for two values and one is null { - foreach (JsonSchemaType? flag in jsonSchemaTypeValues) + foreach (JsonSchemaType flag in jsonSchemaTypeValues) { // Skip if the flag is not set or if it's the Null flag if (schemaType.HasFlag(flag) && flag != JsonSchemaType.Null) @@ -872,10 +737,7 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType schemaType, IOpenApiWriter writer.WriteProperty(OpenApiConstants.Type, flag.ToIdentifier()); } } - if (!Nullable) - { - writer.WriteProperty(nullableProp, true); - } + writer.WriteProperty(nullableProp, true); } else if (!HasMultipleTypes(schemaType)) { @@ -889,5 +751,11 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType schemaType, IOpenApiWriter } } } + + /// + public IOpenApiSchema CreateShallowCopy() + { + return new OpenApiSchema(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs index 428d0649e..193d648df 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs @@ -3,7 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -16,7 +19,7 @@ namespace Microsoft.OpenApi.Models /// then the value is a list of scope names required for the execution. /// For other security scheme types, the array MUST be empty. /// - public class OpenApiSecurityRequirement : Dictionary>, + public class OpenApiSecurityRequirement : Dictionary>, IOpenApiSerializable { /// @@ -34,7 +37,7 @@ public OpenApiSecurityRequirement() /// public void SerializeAsV31(IOpenApiWriter writer) { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); + SerializeInternal(writer, (w, s) => w.WritePropertyName(s.Reference.ReferenceV3)); } /// @@ -42,32 +45,28 @@ public void SerializeAsV31(IOpenApiWriter writer) /// public void SerializeAsV3(IOpenApiWriter writer) { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); + SerializeInternal(writer, (w, s) => w.WritePropertyName(s.Reference.ReferenceV3)); } /// /// Serialize /// - private void SerializeInternal(IOpenApiWriter writer, Action callback) + private void SerializeInternal(IOpenApiWriter writer, Action callback) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); writer.WriteStartObject(); - foreach (var securitySchemeAndScopesValuePair in this) + // Reaching this point means the reference to a specific OpenApiSecurityScheme fails. + // We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what + // string to output. + + foreach (var securitySchemeAndScopesValuePair in this.Where(static p => p.Key?.Target is not null)) { var securityScheme = securitySchemeAndScopesValuePair.Key; var scopes = securitySchemeAndScopesValuePair.Value; - if (securityScheme.Reference == null) - { - // Reaching this point means the reference to a specific OpenApiSecurityScheme fails. - // We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what - // string to output. - continue; - } - - writer.WritePropertyName(securityScheme.Reference.ReferenceV3); + callback(writer, securityScheme); writer.WriteStartArray(); @@ -87,48 +86,19 @@ private void SerializeInternal(IOpenApiWriter writer, Action public void SerializeAsV2(IOpenApiWriter writer) { - Utils.CheckArgumentNull(writer);; - - writer.WriteStartObject(); - - foreach (var securitySchemeAndScopesValuePair in this) - { - var securityScheme = securitySchemeAndScopesValuePair.Key; - var scopes = securitySchemeAndScopesValuePair.Value; - - if (securityScheme.Reference == null) - { - // Reaching this point means the reference to a specific OpenApiSecurityScheme fails. - // We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what - // string to output. - continue; - } - - securityScheme.SerializeAsV2(writer); - - writer.WriteStartArray(); - - foreach (var scope in scopes) - { - writer.WriteValue(scope); - } - - writer.WriteEndArray(); - } - - writer.WriteEndObject(); + SerializeInternal(writer, (w, s) => s.SerializeAsV2(w)); } /// /// Comparer for OpenApiSecurityScheme that only considers the Id in the Reference /// (i.e. the string that will actually be displayed in the written document) /// - private class OpenApiSecuritySchemeReferenceEqualityComparer : IEqualityComparer + private sealed class OpenApiSecuritySchemeReferenceEqualityComparer : IEqualityComparer { /// /// Determines whether the specified objects are equal. /// - public bool Equals(OpenApiSecurityScheme x, OpenApiSecurityScheme y) + public bool Equals(OpenApiSecuritySchemeReference x, OpenApiSecuritySchemeReference y) { if (x == null && y == null) { @@ -140,20 +110,19 @@ public bool Equals(OpenApiSecurityScheme x, OpenApiSecurityScheme y) return false; } - if (x.Reference == null || y.Reference == null) - { - return false; - } - - return x.Reference.Id == y.Reference.Id; + return GetHashCode(x) == GetHashCode(y); } /// /// Returns a hash code for the specified object. /// - public int GetHashCode(OpenApiSecurityScheme obj) + public int GetHashCode(OpenApiSecuritySchemeReference obj) { - return obj?.Reference?.Id == null ? 0 : obj.Reference.Id.GetHashCode(); + if (obj is null) + { + return 0; + } + return string.IsNullOrEmpty(obj?.Reference?.Id) ? 0 : obj.Reference.Id.GetHashCode(); } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs index d9227be25..dddbbffec 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -12,65 +13,34 @@ namespace Microsoft.OpenApi.Models /// /// Security Scheme Object. /// - public class OpenApiSecurityScheme : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiSecurityScheme : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSecurityScheme { - /// - /// REQUIRED. The type of the security scheme. Valid values are "apiKey", "http", "oauth2", "openIdConnect". - /// - public virtual SecuritySchemeType? Type { get; set; } + /// + public SecuritySchemeType? Type { get; set; } - /// - /// A short description for security scheme. CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } + /// + public string Description { get; set; } - /// - /// REQUIRED. The name of the header, query or cookie parameter to be used. - /// - public virtual string Name { get; set; } + /// + public string Name { get; set; } - /// - /// REQUIRED. The location of the API key. Valid values are "query", "header" or "cookie". - /// - public virtual ParameterLocation? In { get; set; } + /// + public ParameterLocation? In { get; set; } - /// - /// REQUIRED. The name of the HTTP Authorization scheme to be used - /// in the Authorization header as defined in RFC7235. - /// - public virtual string Scheme { get; set; } + /// + public string Scheme { get; set; } - /// - /// A hint to the client to identify how the bearer token is formatted. - /// Bearer tokens are usually generated by an authorization server, - /// so this information is primarily for documentation purposes. - /// - public virtual string BearerFormat { get; set; } + /// + public string BearerFormat { get; set; } - /// - /// REQUIRED. An object containing configuration information for the flow types supported. - /// - public virtual OpenApiOAuthFlows Flows { get; set; } + /// + public OpenApiOAuthFlows Flows { get; set; } - /// - /// REQUIRED. OpenId Connect URL to discover OAuth2 configuration values. - /// - public virtual Uri OpenIdConnectUrl { get; set; } + /// + public Uri OpenIdConnectUrl { get; set; } - /// - /// Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); - - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public bool UnresolvedReference { get; set; } - - /// - /// Reference object. - /// - public OpenApiReference Reference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameterless constructor @@ -78,27 +48,26 @@ public class OpenApiSecurityScheme : IOpenApiReferenceable, IOpenApiExtensible public OpenApiSecurityScheme() { } /// - /// Initializes a copy of object + /// Initializes a copy of object /// - public OpenApiSecurityScheme(OpenApiSecurityScheme securityScheme) + internal OpenApiSecurityScheme(IOpenApiSecurityScheme securityScheme) { - Type = securityScheme?.Type; - Description = securityScheme?.Description ?? Description; - Name = securityScheme?.Name ?? Name; - In = securityScheme?.In; - Scheme = securityScheme?.Scheme ?? Scheme; - BearerFormat = securityScheme?.BearerFormat ?? BearerFormat; - Flows = securityScheme?.Flows != null ? new(securityScheme?.Flows) : null; - OpenIdConnectUrl = securityScheme?.OpenIdConnectUrl != null ? new Uri(securityScheme.OpenIdConnectUrl.OriginalString, UriKind.RelativeOrAbsolute) : null; - Extensions = securityScheme?.Extensions != null ? new Dictionary(securityScheme.Extensions) : null; - UnresolvedReference = securityScheme?.UnresolvedReference ?? UnresolvedReference; - Reference = securityScheme?.Reference != null ? new(securityScheme?.Reference) : null; + Utils.CheckArgumentNull(securityScheme); + Type = securityScheme.Type; + Description = securityScheme.Description ?? Description; + Name = securityScheme.Name ?? Name; + In = securityScheme.In; + Scheme = securityScheme.Scheme ?? Scheme; + BearerFormat = securityScheme.BearerFormat ?? BearerFormat; + Flows = securityScheme.Flows != null ? new(securityScheme.Flows) : null; + OpenIdConnectUrl = securityScheme.OpenIdConnectUrl != null ? new Uri(securityScheme.OpenIdConnectUrl.OriginalString, UriKind.RelativeOrAbsolute) : null; + Extensions = securityScheme.Extensions != null ? new Dictionary(securityScheme.Extensions) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } @@ -106,12 +75,12 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -161,7 +130,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio /// /// Serialize to Open Api v2.0 /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); @@ -260,5 +229,11 @@ private static void WriteOAuthFlowForV2(IOpenApiWriter writer, string flowValue, // scopes writer.WriteOptionalMap(OpenApiConstants.Scopes, flow.Scopes, (w, s) => w.WriteValue(s)); } + + /// + public IOpenApiSecurityScheme CreateShallowCopy() + { + return new OpenApiSecurityScheme(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiTag.cs b/src/Microsoft.OpenApi/Models/OpenApiTag.cs index 057cf6d49..91e3aac68 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiTag.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiTag.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -11,32 +12,19 @@ namespace Microsoft.OpenApi.Models /// /// Tag Object. /// - public class OpenApiTag : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiTag : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiTag, IOpenApiDescribedElement { - /// - /// The name of the tag. - /// - public virtual string Name { get; set; } + /// + public string Name { get; set; } - /// - /// A short description for the tag. - /// - public virtual string Description { get; set; } - - /// - /// Additional external documentation for this tag. - /// - public virtual OpenApiExternalDocs ExternalDocs { get; set; } + /// + public string Description { get; set; } - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public OpenApiExternalDocs ExternalDocs { get; set; } - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public bool UnresolvedReference { get; set; } + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameterless constructor @@ -44,21 +32,21 @@ public class OpenApiTag : IOpenApiReferenceable, IOpenApiExtensible public OpenApiTag() { } /// - /// Initializes a copy of an object + /// Initializes a copy of an object /// - public OpenApiTag(OpenApiTag tag) + internal OpenApiTag(IOpenApiTag tag) { - Name = tag?.Name ?? Name; - Description = tag?.Description ?? Description; - ExternalDocs = tag?.ExternalDocs != null ? new(tag.ExternalDocs) : null; - Extensions = tag?.Extensions != null ? new Dictionary(tag.Extensions) : null; - UnresolvedReference = tag?.UnresolvedReference ?? UnresolvedReference; + Utils.CheckArgumentNull(tag); + Name = tag.Name ?? Name; + Description = tag.Description ?? Description; + ExternalDocs = tag.ExternalDocs != null ? new(tag.ExternalDocs) : null; + Extensions = tag.Extensions != null ? new Dictionary(tag.Extensions) : null; } /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); @@ -67,13 +55,13 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { writer.WriteStartObject(); @@ -96,7 +84,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio /// /// Serialize to Open Api v2.0 /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { writer.WriteStartObject(); @@ -114,5 +102,11 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) writer.WriteEndObject(); } + + /// + public IOpenApiTag CreateShallowCopy() + { + return new OpenApiTag(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs b/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs index d7205f37c..e01545c61 100644 --- a/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs +++ b/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs @@ -10,14 +10,12 @@ namespace Microsoft.OpenApi.Models.References; /// The interface type for the model. public abstract class BaseOpenApiReferenceHolder : IOpenApiReferenceHolder where T : class, IOpenApiReferenceable, V where V : IOpenApiSerializable { - internal T _target; /// - public T Target + public virtual T Target { get { - _target ??= Reference.HostDocument.ResolveReferenceTo(Reference); - return _target; + return Reference.HostDocument?.ResolveReferenceTo(Reference); } } /// @@ -28,20 +26,9 @@ protected BaseOpenApiReferenceHolder(BaseOpenApiReferenceHolder source) { Utils.CheckArgumentNull(source); Reference = source.Reference != null ? new(source.Reference) : null; - UnresolvedReference = source.UnresolvedReference; //no need to copy summary and description as if they are not overridden, they will be fetched from the target //if they are, the reference copy will handle it } - private protected BaseOpenApiReferenceHolder(T target, string referenceId, ReferenceType referenceType) - { - _target = target; - - Reference = new OpenApiReference() - { - Id = referenceId, - Type = referenceType, - }; - } /// /// Constructor initializing the reference object. /// @@ -53,9 +40,11 @@ private protected BaseOpenApiReferenceHolder(T target, string referenceId, Refer /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - protected BaseOpenApiReferenceHolder(string referenceId, OpenApiDocument hostDocument, ReferenceType referenceType, string externalResource = null) + protected BaseOpenApiReferenceHolder(string referenceId, OpenApiDocument hostDocument, ReferenceType referenceType, string externalResource) { Utils.CheckArgumentNullOrEmpty(referenceId); + // we're not checking for null hostDocument as it's optional and can be set via additional methods by a walker + // this way object initialization of a whole document is supported Reference = new OpenApiReference() { @@ -66,13 +55,13 @@ protected BaseOpenApiReferenceHolder(string referenceId, OpenApiDocument hostDoc }; } /// - public bool UnresolvedReference { get; set; } + public bool UnresolvedReference { get => Reference is null || Target is null; } /// - public OpenApiReference Reference { get; set; } + public OpenApiReference Reference { get; init; } /// public abstract V CopyReferenceAsTargetElementWithOverrides(V source); /// - public void SerializeAsV3(IOpenApiWriter writer) + public virtual void SerializeAsV3(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { @@ -85,7 +74,7 @@ public void SerializeAsV3(IOpenApiWriter writer) } /// - public void SerializeAsV31(IOpenApiWriter writer) + public virtual void SerializeAsV31(IOpenApiWriter writer) { if (!writer.GetSettings().ShouldInlineReference(Reference)) { diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs index afa22d4e2..4c30328d4 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs @@ -25,20 +25,16 @@ public class OpenApiCallbackReference : BaseOpenApiReferenceHolder - public OpenApiCallbackReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Callback, externalResource) + public OpenApiCallbackReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Callback, externalResource) { } - /// /// Copy constructor /// - /// The callback reference to copy - public OpenApiCallbackReference(OpenApiCallbackReference callback):base(callback) - { - } - - internal OpenApiCallbackReference(OpenApiCallback target, string referenceId):base(target, referenceId, ReferenceType.Callback) + /// The reference to copy + private OpenApiCallbackReference(OpenApiCallbackReference callback):base(callback) { + } /// @@ -59,5 +55,11 @@ public override void SerializeAsV2(IOpenApiWriter writer) // examples components are not supported in OAS 2.0 Reference.SerializeAsV2(writer); } + + /// + public IOpenApiCallback CreateShallowCopy() + { + return new OpenApiCallbackReference(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs index 9a1c5ae16..edfe27b61 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs @@ -25,19 +25,14 @@ public class OpenApiExampleReference : BaseOpenApiReferenceHolder - public OpenApiExampleReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Example, externalResource) + public OpenApiExampleReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Example, externalResource) { } - /// /// Copy constructor /// - /// The reference to copy. - public OpenApiExampleReference(OpenApiExampleReference example):base(example) - { - } - - internal OpenApiExampleReference(OpenApiExample target, string referenceId):base(target, referenceId, ReferenceType.Example) + /// The example reference to copy + private OpenApiExampleReference(OpenApiExampleReference example):base(example) { } @@ -88,5 +83,11 @@ public override void SerializeAsV2(IOpenApiWriter writer) // examples components are not supported in OAS 2.0 Reference.SerializeAsV2(writer); } + + /// + public IOpenApiExample CreateShallowCopy() + { + return new OpenApiExampleReference(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs index dfbee5ce7..719cdce3a 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs @@ -6,7 +6,6 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models.Interfaces; -using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models.References { @@ -25,7 +24,7 @@ public class OpenApiHeaderReference : BaseOpenApiReferenceHolder - public OpenApiHeaderReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Header, externalResource) + public OpenApiHeaderReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Header, externalResource) { } @@ -33,11 +32,7 @@ public OpenApiHeaderReference(string referenceId, OpenApiDocument hostDocument, /// Copy constructor /// /// The object to copy - public OpenApiHeaderReference(OpenApiHeaderReference header):base(header) - { - } - - internal OpenApiHeaderReference(OpenApiHeader target, string referenceId):base(target, referenceId, ReferenceType.Header) + private OpenApiHeaderReference(OpenApiHeaderReference header):base(header) { } @@ -64,7 +59,7 @@ public string Description public bool AllowEmptyValue { get => Target?.AllowEmptyValue ?? default; } /// - public OpenApiSchema Schema { get => Target?.Schema; } + public IOpenApiSchema Schema { get => Target?.Schema; } /// public ParameterStyle? Style { get => Target?.Style; } @@ -92,5 +87,11 @@ public override IOpenApiHeader CopyReferenceAsTargetElementWithOverrides(IOpenAp { return source is OpenApiHeader ? new OpenApiHeader(this) : source; } + + /// + public IOpenApiHeader CreateShallowCopy() + { + return new OpenApiHeaderReference(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs index f177bee2c..f91b5711b 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiLinkReference.cs @@ -24,17 +24,14 @@ public class OpenApiLinkReference : BaseOpenApiReferenceHolder - public OpenApiLinkReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Link, externalResource) + public OpenApiLinkReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Link, externalResource) { } /// /// Copy constructor. /// /// The reference to copy - public OpenApiLinkReference(OpenApiLinkReference reference):base(reference) - { - } - internal OpenApiLinkReference(OpenApiLink target, string referenceId):base(target, referenceId, ReferenceType.Link) + private OpenApiLinkReference(OpenApiLinkReference reference):base(reference) { } @@ -80,5 +77,11 @@ public override IOpenApiLink CopyReferenceAsTargetElementWithOverrides(IOpenApiL { return source is OpenApiLink ? new OpenApiLink(this) : source; } + + /// + public IOpenApiLink CreateShallowCopy() + { + return new OpenApiLinkReference(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs index 82c73afda..d337b841e 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs @@ -23,7 +23,7 @@ public class OpenApiParameterReference : BaseOpenApiReferenceHolder - public OpenApiParameterReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Parameter, externalResource) + public OpenApiParameterReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Parameter, externalResource) { } @@ -31,16 +31,12 @@ public OpenApiParameterReference(string referenceId, OpenApiDocument hostDocumen /// Copy constructor /// /// The parameter reference to copy - public OpenApiParameterReference(OpenApiParameterReference parameter):base(parameter) - { - } - - internal OpenApiParameterReference(OpenApiParameter target, string referenceId):base(target, referenceId, ReferenceType.Parameter) + private OpenApiParameterReference(OpenApiParameterReference parameter):base(parameter) { } /// - public string Name { get => Target.Name; } + public string Name { get => Target?.Name; } /// public string Description @@ -68,7 +64,7 @@ public string Description public bool AllowReserved { get => Target?.AllowReserved ?? default; } /// - public OpenApiSchema Schema { get => Target?.Schema; } + public IOpenApiSchema Schema { get => Target?.Schema; } /// public IDictionary Examples { get => Target?.Examples; } @@ -86,15 +82,21 @@ public string Description public bool Explode { get => Target?.Explode ?? default; } /// - public IDictionary Content { get => Target.Content; } + public IDictionary Content { get => Target?.Content; } /// - public IDictionary Extensions { get => Target.Extensions; } + public IDictionary Extensions { get => Target?.Extensions; } /// public override IOpenApiParameter CopyReferenceAsTargetElementWithOverrides(IOpenApiParameter source) { return source is OpenApiParameter ? new OpenApiParameter(this) : source; } + + /// + public IOpenApiParameter CreateShallowCopy() + { + return new OpenApiParameterReference(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs index f36bca3fd..038e1cb13 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs @@ -24,12 +24,17 @@ public class OpenApiPathItemReference : BaseOpenApiReferenceHolder - public OpenApiPathItemReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null): base(referenceId, hostDocument, ReferenceType.PathItem, externalResource) + public OpenApiPathItemReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null): base(referenceId, hostDocument, ReferenceType.PathItem, externalResource) { } - internal OpenApiPathItemReference(OpenApiPathItem target, string referenceId):base(target, referenceId, ReferenceType.PathItem) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiPathItemReference(OpenApiPathItemReference pathItem):base(pathItem) { + } /// @@ -76,6 +81,12 @@ public override IOpenApiPathItem CopyReferenceAsTargetElementWithOverrides(IOpen return source is OpenApiPathItem ? new OpenApiPathItem(this) : source; } + /// + public IOpenApiPathItem CreateShallowCopy() + { + return new OpenApiPathItemReference(this); + } + /// public override void SerializeAsV2(IOpenApiWriter writer) { diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs index d698dd092..966d3aad1 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs @@ -25,11 +25,16 @@ public class OpenApiRequestBodyReference : BaseOpenApiReferenceHolder - public OpenApiRequestBodyReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.RequestBody, externalResource) + public OpenApiRequestBodyReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.RequestBody, externalResource) { } - internal OpenApiRequestBodyReference(OpenApiRequestBody target, string referenceId):base(target, referenceId, ReferenceType.RequestBody) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiRequestBodyReference(OpenApiRequestBodyReference openApiRequestBodyReference):base(openApiRequestBodyReference) { + } /// @@ -89,5 +94,11 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter return Content.First().Value.Schema.Properties.Select(x => new OpenApiParameterReference(x.Key, Reference.HostDocument)); } + + /// + public IOpenApiRequestBody CreateShallowCopy() + { + return new OpenApiRequestBodyReference(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs index ef6b68fff..9fbfb47a0 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs @@ -23,12 +23,16 @@ public class OpenApiResponseReference : BaseOpenApiReferenceHolder - public OpenApiResponseReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Response, externalResource) + public OpenApiResponseReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Response, externalResource) { } - - internal OpenApiResponseReference(OpenApiResponse target, string referenceId):base(target, referenceId, ReferenceType.Response) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiResponseReference(OpenApiResponseReference openApiResponseReference):base(openApiResponseReference) { + } /// @@ -61,5 +65,11 @@ public override IOpenApiResponse CopyReferenceAsTargetElementWithOverrides(IOpen { return source is OpenApiResponse ? new OpenApiResponse(this) : source; } + + /// + public IOpenApiResponse CreateShallowCopy() + { + return new OpenApiResponseReference(this); + } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs index 731f9c1af..9252d6b89 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; using System; using System.Collections.Generic; @@ -12,79 +13,8 @@ namespace Microsoft.OpenApi.Models.References /// /// Schema reference object /// - public class OpenApiSchemaReference : OpenApiSchema, IOpenApiReferenceHolder + public class OpenApiSchemaReference : BaseOpenApiReferenceHolder, IOpenApiSchema { -#nullable enable - private OpenApiSchema? _target; - private readonly OpenApiReference _reference; - private string? _description; - private JsonNode? _default; - private JsonNode? _example; - private IList? _examples; - private bool? _nullable; - private IDictionary? _properties; - private string? _title; - private string? _schema; - private string? _comment; - private string? _id; - private string? _dynamicRef; - private string? _dynamicAnchor; - private IDictionary? _vocabulary; - private IDictionary? _definitions; - private decimal? _v31ExclusiveMaximum; - private decimal? _v31ExclusiveMinimum; - private bool? _unEvaluatedProperties; - private JsonSchemaType? _type; - private string? _const; - private string? _format; - private decimal? _maximum; - private bool? _exclusiveMaximum; - private decimal? _minimum; - private bool? _exclusiveMinimum; - private int? _maxLength; - private int? _minLength; - private string? _pattern; - private decimal? _multipleOf; - private bool? _readOnly; - private bool? _writeOnly; - private IList? _allOf; - private IList? _oneOf; - private IList? _anyOf; - private OpenApiSchema? _not; - private ISet? _required; - private OpenApiSchema _items; - private int? _maxItems; - private int? _minItems; - private bool? _uniqueItems; - private IDictionary? _patternProperties; - private int? _maxProperties; - private int? _minProperties; - private bool? _additionalPropertiesAllowed; - private OpenApiSchema? _additionalProperties; - private OpenApiDiscriminator? _discriminator; - private OpenApiExternalDocs? _externalDocs; - private bool? _deprecated; - private OpenApiXml? _xml; - private IDictionary? _extensions; - private bool? _unevaluatedProperties; - private IList? _enum; - - /// - /// Gets the target schema. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiSchema? Target -#nullable restore - { - get - { - _target ??= Reference.HostDocument?.ResolveReferenceTo(_reference); - return _target; - } - } - /// /// Constructor initializing the reference object. /// @@ -95,214 +25,179 @@ public OpenApiSchema? Target /// 1. a absolute/relative file path, for example: ../commons/pet.json /// 2. a Url, for example: http://localhost/pet.json /// - public OpenApiSchemaReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiSchemaReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Schema, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Schema, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiSchemaReference(OpenApiSchema target, string referenceId) + /// + /// Copy constructor + /// + /// The schema reference to copy + private OpenApiSchemaReference(OpenApiSchemaReference schema):base(schema) { - _target = target; + } - _reference = new OpenApiReference() + /// + public string Description + { + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set { - Id = referenceId, - Type = ReferenceType.Schema, - }; + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override string Title { get => string.IsNullOrEmpty(_title) ? Target?.Title : _title; set => _title = value; } + public string Title { get => Target?.Title; } /// - public override string Schema { get => string.IsNullOrEmpty(_schema) ? Target?.Schema : _schema; set => _schema = value; } + public string Schema { get => Target?.Schema; } /// - public override string Id { get => string.IsNullOrEmpty(_id) ? Target?.Id : _id; set => _id = value; } + public string Id { get => Target?.Id; } /// - public override string Comment { get => string.IsNullOrEmpty(_comment) ? Target?.Comment : _comment; set => _comment = value; } + public string Comment { get => Target?.Comment; } /// - public override IDictionary Vocabulary { get => _vocabulary is not null ? _vocabulary : Target?.Vocabulary; set => _vocabulary = value; } + public IDictionary Vocabulary { get => Target?.Vocabulary; } /// - public override string DynamicRef { get => string.IsNullOrEmpty(_dynamicRef) ? Target?.DynamicRef : _dynamicRef; set => _dynamicRef = value; } + public string DynamicRef { get => Target?.DynamicRef; } /// - public override string DynamicAnchor { get => string.IsNullOrEmpty(_dynamicAnchor) ? Target?.DynamicAnchor : _dynamicAnchor; set => _dynamicAnchor = value; } + public string DynamicAnchor { get => Target?.DynamicAnchor; } /// - public override IDictionary Definitions { get => _definitions is not null ? _definitions : Target?.Definitions; set => _definitions = value; } + public IDictionary Definitions { get => Target?.Definitions; } /// - public override decimal? V31ExclusiveMaximum { get => _v31ExclusiveMaximum is not null ? _v31ExclusiveMaximum.Value : Target?.V31ExclusiveMaximum; set => _v31ExclusiveMaximum = value; } + public decimal? V31ExclusiveMaximum { get => Target?.V31ExclusiveMaximum; } /// - public override decimal? V31ExclusiveMinimum { get => _v31ExclusiveMinimum is not null ? _v31ExclusiveMinimum.Value : Target?.V31ExclusiveMinimum; set => _v31ExclusiveMinimum = value; } + public decimal? V31ExclusiveMinimum { get => Target?.V31ExclusiveMinimum; } /// - public override bool UnEvaluatedProperties { get => _unEvaluatedProperties is not null ? _unEvaluatedProperties.Value : Target?.UnEvaluatedProperties ?? false; set => _unEvaluatedProperties = value; } + public bool UnEvaluatedProperties { get => Target?.UnEvaluatedProperties ?? false; } /// - public override JsonSchemaType? Type { get => _type is not null ? _type.Value : Target?.Type; set => _type = value; } + public JsonSchemaType? Type { get => Target?.Type; } /// - public override string Const { get => string.IsNullOrEmpty(_const) ? Target?.Const : _const; set => _const = value; } + public string Const { get => Target?.Const; } /// - public override string Format { get => string.IsNullOrEmpty(_format) ? Target?.Format : _format; set => _format = value; } + public string Format { get => Target?.Format; } /// - public override string Description - { - get => string.IsNullOrEmpty(_description) ? Target?.Description : _description; - set => _description = value; - } + public decimal? Maximum { get => Target?.Maximum; } /// - public override decimal? Maximum { get => _maximum is not null ? _maximum : Target?.Maximum; set => _maximum = value; } + public bool? ExclusiveMaximum { get => Target?.ExclusiveMaximum; } /// - public override bool? ExclusiveMaximum { get => _exclusiveMaximum is not null ? _exclusiveMaximum : Target?.ExclusiveMaximum; set => _exclusiveMaximum = value; } + public decimal? Minimum { get => Target?.Minimum; } /// - public override decimal? Minimum { get => _minimum is not null ? _minimum : Target?.Minimum; set => _minimum = value; } + public bool? ExclusiveMinimum { get => Target?.ExclusiveMinimum; } /// - public override bool? ExclusiveMinimum { get => _exclusiveMinimum is not null ? _exclusiveMinimum : Target?.ExclusiveMinimum; set => _exclusiveMinimum = value; } + public int? MaxLength { get => Target?.MaxLength; } /// - public override int? MaxLength { get => _maxLength is not null ? _maxLength : Target?.MaxLength; set => _maxLength = value; } + public int? MinLength { get => Target?.MinLength; } /// - public override int? MinLength { get => _minLength is not null ? _minLength : Target?.MinLength; set => _minLength = value; } + public string Pattern { get => Target?.Pattern; } /// - public override string Pattern { get => string.IsNullOrEmpty(_pattern) ? Target?.Pattern : _pattern; set => _pattern = value; } + public decimal? MultipleOf { get => Target?.MultipleOf; } /// - public override decimal? MultipleOf { get => _multipleOf is not null ? _multipleOf : Target?.MultipleOf; set => _multipleOf = value; } + public JsonNode Default { get => Target?.Default; } /// - public override JsonNode Default { get => _default is not null ? _default : Target?.Default; set => _default = value; } + public bool ReadOnly { get => Target?.ReadOnly ?? false; } /// - public override bool ReadOnly { get => _readOnly is not null ? _readOnly.Value : Target?.ReadOnly ?? false; set => _readOnly = value; } + public bool WriteOnly { get => Target?.WriteOnly ?? false; } /// - public override bool WriteOnly { get => _writeOnly is not null ? _writeOnly.Value : Target?.WriteOnly ?? false; set => _writeOnly = value; } + public IList AllOf { get => Target?.AllOf; } /// - public override IList AllOf { get => _allOf is not null ? _allOf : Target?.AllOf; set => _allOf = value; } + public IList OneOf { get => Target?.OneOf; } /// - public override IList OneOf { get => _oneOf is not null ? _oneOf : Target?.OneOf; set => _oneOf = value; } + public IList AnyOf { get => Target?.AnyOf; } /// - public override IList AnyOf { get => _anyOf is not null ? _anyOf : Target?.AnyOf; set => _anyOf = value; } + public IOpenApiSchema Not { get => Target?.Not; } /// - public override OpenApiSchema Not { get => _not is not null ? _not : Target?.Not; set => _not = value; } + public ISet Required { get => Target?.Required; } /// - public override ISet Required { get => _required is not null ? _required : Target?.Required; set => _required = value; } + public IOpenApiSchema Items { get => Target?.Items; } /// - public override OpenApiSchema Items { get => _items is not null ? _items : Target?.Items; set => _items = value; } + public int? MaxItems { get => Target?.MaxItems; } /// - public override int? MaxItems { get => _maxItems is not null ? _maxItems : Target?.MaxItems; set => _maxItems = value; } + public int? MinItems { get => Target?.MinItems; } /// - public override int? MinItems { get => _minItems is not null ? _minItems : Target?.MinItems; set => _minItems = value; } + public bool? UniqueItems { get => Target?.UniqueItems; } /// - public override bool? UniqueItems { get => _uniqueItems is not null ? _uniqueItems : Target?.UniqueItems; set => _uniqueItems = value; } + public IDictionary Properties { get => Target?.Properties; } /// - public override IDictionary Properties { get => _properties is not null ? _properties : Target?.Properties; set => _properties = value; } + public IDictionary PatternProperties { get => Target?.PatternProperties; } /// - public override IDictionary PatternProperties { get => _patternProperties is not null ? _patternProperties : Target?.PatternProperties; set => _patternProperties = value; } + public int? MaxProperties { get => Target?.MaxProperties; } /// - public override int? MaxProperties { get => _maxProperties is not null ? _maxProperties : Target?.MaxProperties; set => _maxProperties = value; } + public int? MinProperties { get => Target?.MinProperties; } /// - public override int? MinProperties { get => _minProperties is not null ? _minProperties : Target?.MinProperties; set => _minProperties = value; } + public bool AdditionalPropertiesAllowed { get => Target?.AdditionalPropertiesAllowed ?? true; } /// - public override bool AdditionalPropertiesAllowed { get => _additionalPropertiesAllowed is not null ? _additionalPropertiesAllowed.Value : Target?.AdditionalPropertiesAllowed ?? true; set => _additionalPropertiesAllowed = value; } + public IOpenApiSchema AdditionalProperties { get => Target?.AdditionalProperties; } /// - public override OpenApiSchema AdditionalProperties { get => _additionalProperties is not null ? _additionalProperties : Target?.AdditionalProperties; set => _additionalProperties = value; } + public OpenApiDiscriminator Discriminator { get => Target?.Discriminator; } /// - public override OpenApiDiscriminator Discriminator { get => _discriminator is not null ? _discriminator : Target?.Discriminator; set => _discriminator = value; } + public JsonNode Example { get => Target?.Example; } /// - public override JsonNode Example { get => _example is not null ? _example : Target?.Example; set => _example = value; } + public IList Examples { get => Target?.Examples; } /// - public override IList Examples { get => _examples is not null ? _examples : Target?.Examples; set => _examples = value; } + public IList Enum { get => Target?.Enum; } /// - public override IList Enum { get => _enum is not null ? _enum : Target?.Enum; set => _enum = value; } + public bool UnevaluatedProperties { get => Target?.UnevaluatedProperties ?? false; } /// - public override bool Nullable { get => _nullable is not null ? _nullable.Value : Target?.Nullable ?? false; set => _nullable = value; } + public OpenApiExternalDocs ExternalDocs { get => Target?.ExternalDocs; } /// - public override bool UnevaluatedProperties { get => _unevaluatedProperties is not null ? _unevaluatedProperties.Value : Target?.UnevaluatedProperties ?? false; set => _unevaluatedProperties = value; } + public bool Deprecated { get => Target?.Deprecated ?? false; } /// - public override OpenApiExternalDocs ExternalDocs { get => _externalDocs is not null ? _externalDocs : Target?.ExternalDocs; set => _externalDocs = value; } + public OpenApiXml Xml { get => Target?.Xml; } /// - public override bool Deprecated { get => _deprecated is not null ? _deprecated.Value : Target?.Deprecated ?? false; set => _deprecated = value; } + public IDictionary Extensions { get => Target?.Extensions; } + /// - public override OpenApiXml Xml { get => _xml is not null ? _xml : Target?.Xml; set => _xml = value; } + public IDictionary UnrecognizedKeywords { get => Target?.UnrecognizedKeywords; } + /// - public override IDictionary Extensions { get => _extensions is not null ? _extensions : Target?.Extensions; set => _extensions = value; } + public IDictionary Annotations { get => Target?.Annotations; } /// public override void SerializeAsV31(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - // If Loop is detected then just Serialize as a reference. - else if (!writer.GetSettings().LoopDetector.PushLoop(this)) - { - writer.GetSettings().LoopDetector.SaveLoop(this); - _reference.SerializeAsV31(writer); - return; - } - - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - writer.GetSettings().LoopDetector.PopLoop(); + SerializeAsWithoutLoops(writer, (w, element) => (element is IOpenApiSchema s ? CopyReferenceAsTargetElementWithOverrides(s) : element).SerializeAsV3(w)); } /// public override void SerializeAsV3(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - // If Loop is detected then just Serialize as a reference. - else if (!writer.GetSettings().LoopDetector.PushLoop(this)) - { - writer.GetSettings().LoopDetector.SaveLoop(this); - _reference.SerializeAsV3(writer); - return; - } - - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - writer.GetSettings().LoopDetector.PopLoop(); + SerializeAsWithoutLoops(writer, (w, element) => element.SerializeAsV3(w)); } - /// - internal override void SerializeAsV2( - IOpenApiWriter writer, - ISet parentRequiredProperties, - string propertyName) + public override void SerializeAsV2(IOpenApiWriter writer) + { + SerializeAsWithoutLoops(writer, (w, element) => element.SerializeAsV2(w)); + } + private void SerializeAsWithoutLoops(IOpenApiWriter writer, Action action) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) + if (!writer.GetSettings().ShouldInlineReference(Reference)) { - _reference.SerializeAsV2(writer); + action(writer, Reference); + } + // If Loop is detected then just Serialize as a reference. + else if (!writer.GetSettings().LoopDetector.PushLoop(this)) + { + writer.GetSettings().LoopDetector.SaveLoop(this); + action(writer, Reference); } else { - base.SerializeAsV2(writer, parentRequiredProperties, propertyName); + SerializeInternal(writer, (w, element) => action(w, element)); + writer.GetSettings().LoopDetector.PopLoop(); } - } + } /// - public override void SerializeAsV2(IOpenApiWriter writer) + public override IOpenApiSchema CopyReferenceAsTargetElementWithOverrides(IOpenApiSchema source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); - } + return source is OpenApiSchema ? new OpenApiSchema(this) : source; } - /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiSchema CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - action(writer, Target); + return new OpenApiSchemaReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs index c1dafa80f..75ca30573 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiSecuritySchemeReference.cs @@ -4,147 +4,80 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Models.References { /// /// Security Scheme Object Reference. /// - public class OpenApiSecuritySchemeReference : OpenApiSecurityScheme, IOpenApiReferenceHolder + public class OpenApiSecuritySchemeReference : BaseOpenApiReferenceHolder, IOpenApiSecurityScheme { - internal OpenApiSecurityScheme _target; - private readonly OpenApiReference _reference; - private string _description; - - /// - /// Gets the target security scheme. - /// - /// - /// If the reference is not resolved, this will return null. - /// - public OpenApiSecurityScheme Target - { - get - { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiSecurityScheme resolved = new OpenApiSecurityScheme(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; - } - } - /// /// Constructor initializing the reference object. /// /// The reference Id. /// The host OpenAPI document. /// The externally referenced file. - public OpenApiSecuritySchemeReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null) + public OpenApiSecuritySchemeReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.SecurityScheme, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - _reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.SecurityScheme, - ExternalResource = externalResource - }; - - Reference = _reference; } - - internal OpenApiSecuritySchemeReference(string referenceId, OpenApiSecurityScheme target) + /// + /// Copy constructor + /// + /// The reference to copy + private OpenApiSecuritySchemeReference(OpenApiSecuritySchemeReference openApiSecuritySchemeReference):base(openApiSecuritySchemeReference) { - _target = target; - - _reference = new OpenApiReference() - { - Id = referenceId, - Type = ReferenceType.SecurityScheme, - }; + } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override string Name { get => Target.Name; set => Target.Name = value; } + public string Name { get => Target?.Name; } /// - public override ParameterLocation? In { get => Target.In; set => Target.In = value; } + public ParameterLocation? In { get => Target?.In; } /// - public override string Scheme { get => Target.Scheme; set => Target.Scheme = value; } + public string Scheme { get => Target?.Scheme; } /// - public override string BearerFormat { get => Target.BearerFormat; set => Target.BearerFormat = value; } + public string BearerFormat { get => Target?.BearerFormat; } /// - public override OpenApiOAuthFlows Flows { get => Target.Flows; set => Target.Flows = value; } + public OpenApiOAuthFlows Flows { get => Target?.Flows; } /// - public override Uri OpenIdConnectUrl { get => Target.OpenIdConnectUrl; set => Target.OpenIdConnectUrl = value; } + public Uri OpenIdConnectUrl { get => Target?.OpenIdConnectUrl; } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override SecuritySchemeType? Type { get => Target.Type; set => Target.Type = value; } - - /// - public override void SerializeAsV3(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV3(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } - } - - /// - public override void SerializeAsV31(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV31(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } - } + public SecuritySchemeType? Type { get => Target?.Type; } /// - public override void SerializeAsV2(IOpenApiWriter writer) + public override IOpenApiSecurityScheme CopyReferenceAsTargetElementWithOverrides(IOpenApiSecurityScheme source) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) - { - _reference.SerializeAsV2(writer); - return; - } - else - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); - } + return source is OpenApiSecurityScheme ? new OpenApiSecurityScheme(this) : source; } /// - private void SerializeInternal(IOpenApiWriter writer, - Action action) + public IOpenApiSecurityScheme CreateShallowCopy() { - Utils.CheckArgumentNull(writer);; - action(writer, Target); + return new OpenApiSecuritySchemeReference(this); } } } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs index 09afa3655..6f218fc13 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs @@ -5,31 +5,23 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Models.References { /// /// Tag Object Reference /// - public class OpenApiTagReference : OpenApiTag, IOpenApiReferenceHolder + public class OpenApiTagReference : BaseOpenApiReferenceHolder, IOpenApiTag { - internal OpenApiTag _target; - - /// - /// Reference. - /// - public OpenApiReference Reference { get; set; } - /// /// Resolved target of the reference. /// - public OpenApiTag Target + public override OpenApiTag Target { get { - _target ??= Reference.HostDocument?.Tags.FirstOrDefault(t => StringComparer.Ordinal.Equals(t.Name, Reference.Id)); - return _target; + return Reference.HostDocument?.Tags.FirstOrDefault(t => StringComparer.Ordinal.Equals(t.Name, Reference.Id)); } } @@ -38,85 +30,47 @@ public OpenApiTag Target /// /// The reference Id. /// The host OpenAPI document. - public OpenApiTagReference(string referenceId, OpenApiDocument hostDocument) + /// Optional: External resource in the reference. + /// It may be: + /// 1. a absolute/relative file path, for example: ../commons/pet.json + /// 2. a Url, for example: http://localhost/pet.json + /// + public OpenApiTagReference(string referenceId, OpenApiDocument hostDocument = null, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Tag, externalResource) { - Utils.CheckArgumentNullOrEmpty(referenceId); - - Reference = new OpenApiReference() - { - Id = referenceId, - HostDocument = hostDocument, - Type = ReferenceType.Tag - }; } - /// - /// Copy Constructor + /// Copy constructor /// - /// The source to copy information from. - public OpenApiTagReference(OpenApiTagReference source):base() + /// The reference to copy + private OpenApiTagReference(OpenApiTagReference openApiTagReference):base(openApiTagReference) { - Reference = source?.Reference != null ? new(source.Reference) : null; - _target = source?._target; + } - private const string ReferenceErrorMessage = "Setting the value from the reference is not supported, use the target property instead."; /// - public override string Description { get => Target.Description; set => throw new InvalidOperationException(ReferenceErrorMessage); } + public string Description + { + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + } /// - public override OpenApiExternalDocs ExternalDocs { get => Target.ExternalDocs; set => throw new InvalidOperationException(ReferenceErrorMessage); } + public OpenApiExternalDocs ExternalDocs { get => Target?.ExternalDocs; } /// - public override IDictionary Extensions { get => Target.Extensions; set => throw new InvalidOperationException(ReferenceErrorMessage); } + public IDictionary Extensions { get => Target?.Extensions; } /// - public override string Name { get => Target.Name; set => throw new InvalidOperationException(ReferenceErrorMessage); } - + public string Name { get => Target?.Name; } /// - public override void SerializeAsV3(IOpenApiWriter writer) + public override IOpenApiTag CopyReferenceAsTargetElementWithOverrides(IOpenApiTag source) { - if (!writer.GetSettings().ShouldInlineReference(Reference)) - { - Reference.SerializeAsV3(writer); - } - else - { - SerializeInternal(writer); - } - } - - /// - public override void SerializeAsV31(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(Reference)) - { - Reference.SerializeAsV31(writer); - } - else - { - SerializeInternal(writer); - } - } - - /// - public override void SerializeAsV2(IOpenApiWriter writer) - { - if (!writer.GetSettings().ShouldInlineReference(Reference)) - { - Reference.SerializeAsV2(writer); - } - else - { - SerializeInternal(writer); - } + return source is OpenApiTag ? new OpenApiTag(this) : source; } /// - private void SerializeInternal(IOpenApiWriter writer) + public IOpenApiTag CreateShallowCopy() { - Utils.CheckArgumentNull(writer); - writer.WriteValue(Name); + return new OpenApiTagReference(this); } } } diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 4aad45278..bac24a51d 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -60,11 +60,9 @@ public ReadResult Read(MemoryStream input, /// /// The JsonNode input. /// The Reader settings to be used during parsing. - /// The OpenAPI format. /// public ReadResult Read(JsonNode jsonNode, - OpenApiReaderSettings settings, - string format = null) + OpenApiReaderSettings settings) { if (jsonNode is null) throw new ArgumentNullException(nameof(jsonNode)); if (settings is null) throw new ArgumentNullException(nameof(settings)); diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 33bea8fb5..c86c014da 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -39,7 +39,11 @@ public static ReadResult Load(MemoryStream stream, string format = null, OpenApiReaderSettings settings = null) { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(stream); +#else if (stream is null) throw new ArgumentNullException(nameof(stream)); +#endif settings ??= new OpenApiReaderSettings(); // Get the format of the stream if not provided @@ -112,7 +116,11 @@ public static async Task LoadAsync(string url, OpenApiSpecVersion version, /// public static async Task LoadAsync(Stream input, string format = null, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(input); +#else if (input is null) throw new ArgumentNullException(nameof(input)); +#endif settings ??= new OpenApiReaderSettings(); Stream preparedStream; @@ -160,7 +168,11 @@ public static async Task LoadAsync(Stream input, CancellationToken token = default) where T : IOpenApiElement { Utils.CheckArgumentNull(openApiDocument); +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(input); +#else if (input is null) throw new ArgumentNullException(nameof(input)); +#endif if (input is MemoryStream memoryStream) { return Load(memoryStream, version, format, openApiDocument, out var _, settings); @@ -185,7 +197,11 @@ public static ReadResult Parse(string input, string format = null, OpenApiReaderSettings settings = null) { - if (input is null) throw new ArgumentNullException(nameof(input)); +#if NET6_0_OR_GREATER + ArgumentException.ThrowIfNullOrEmpty(input); +#else + if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input)); +#endif format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); @@ -212,7 +228,11 @@ public static T Parse(string input, string format = null, OpenApiReaderSettings settings = null) where T : IOpenApiElement { - if (input is null) throw new ArgumentNullException(nameof(input)); +#if NET6_0_OR_GREATER + ArgumentException.ThrowIfNullOrEmpty(input); +#else + if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input)); +#endif format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); @@ -258,10 +278,13 @@ private static ReadResult InternalLoad(MemoryStream input, string format, OpenAp { throw new InvalidOperationException("Loading external references are not supported when using synchronous methods."); } + if (input.Length == 0 || input.Position == input.Length) + { + throw new ArgumentException($"Cannot parse the stream: {nameof(input)} is empty or contains no elements."); + } var reader = OpenApiReaderRegistry.GetReader(format); var readResult = reader.Read(input, settings); - return readResult; } @@ -278,11 +301,12 @@ private static ReadResult InternalLoad(MemoryStream input, string format, OpenAp var response = await _httpClient.GetAsync(url, token).ConfigureAwait(false); var mediaType = response.Content.Headers.ContentType.MediaType; var contentType = mediaType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0]; - format = contentType.Split('/').LastOrDefault(); + format = contentType.Split('/').Last().Split('+').Last().Split('-').Last(); + // for non-standard MIME types e.g. text/x-yaml used in older libs or apps #if NETSTANDARD2_0 stream = await response.Content.ReadAsStreamAsync(); #else - stream = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false);; + stream = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false); #endif return (stream, format); } @@ -321,8 +345,12 @@ private static string InspectInputFormat(string input) private static string InspectStreamFormat(Stream stream) { - if (stream == null) throw new ArgumentNullException(nameof(stream)); - +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(stream); +#else + if (stream is null) throw new ArgumentNullException(nameof(stream)); +#endif + long initialPosition = stream.Position; int firstByte = stream.ReadByte(); diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs index 92dd24138..16456c400 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyFieldMapParameter.cs @@ -4,6 +4,7 @@ using System; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.ParseNodes { @@ -15,7 +16,7 @@ internal class AnyFieldMapParameter public AnyFieldMapParameter( Func propertyGetter, Action propertySetter, - Func SchemaGetter = null) + Func SchemaGetter = null) { this.PropertyGetter = propertyGetter; this.PropertySetter = propertySetter; @@ -35,6 +36,6 @@ public AnyFieldMapParameter( /// /// Function to get the schema to apply to the property. /// - public Func SchemaGetter { get; } + public Func SchemaGetter { get; } } } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs index 4d365125b..52397aed9 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/AnyMapFieldMapParameter.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.ParseNodes { @@ -17,7 +18,7 @@ public AnyMapFieldMapParameter( Func> propertyMapGetter, Func propertyGetter, Action propertySetter, - Func schemaGetter) + Func schemaGetter) { this.PropertyMapGetter = propertyMapGetter; this.PropertyGetter = propertyGetter; @@ -43,6 +44,6 @@ public AnyMapFieldMapParameter( /// /// Function to get the schema to apply to the property. /// - public Func SchemaGetter { get; } + public Func SchemaGetter { get; } } } diff --git a/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs b/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs index d8740857b..b71593dca 100644 --- a/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs +++ b/src/Microsoft.OpenApi/Reader/ParseNodes/MapNode.cs @@ -124,7 +124,6 @@ public T GetReferencedObject(ReferenceType referenceType, string referenceId, { return new() { - UnresolvedReference = true, Reference = Context.VersionService.ConvertToOpenApiReference(referenceId, referenceType, summary, description) }; } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs index d225899cc..00bfc2d74 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiContactDeserializer.cs @@ -32,7 +32,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs index a09d2eab9..0aa2b8093 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs @@ -111,7 +111,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _openApiPatternFields = new() { // We have no semantics to verify X- nodes, therefore treat them as just values. - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static void MakeServers(IList servers, ParsingContext context, RootNode rootNode) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs index 6fc438542..312313585 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiExternalDocsDeserializer.cs @@ -30,7 +30,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _externalDocsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs index bc2333e46..9c712b0a3 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -95,12 +95,15 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static OpenApiSchema GetOrCreateSchema(OpenApiHeader p) { - return p.Schema ??= new(); + return p.Schema switch { + OpenApiSchema schema => schema, + _ => (OpenApiSchema)(p.Schema = new OpenApiSchema()), + }; } public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) @@ -113,7 +116,7 @@ public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocu property.ParseField(header, _headerFixedFields, _headerPatternFields, hostDocument); } - var schema = node.Context.GetFromTempStorage("schema"); + var schema = node.Context.GetFromTempStorage("schema"); if (schema != null) { header.Schema = schema; diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs index 74c3ac917..0d33e896c 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiInfoDeserializer.cs @@ -44,7 +44,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _infoPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs index 8eae690ed..d4a95de89 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiLicenseDeserializer.cs @@ -28,7 +28,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs index 140ad9f3d..37c95c9b2 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs @@ -9,6 +9,7 @@ using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Models.Interfaces; +using System; namespace Microsoft.OpenApi.Reader.V2 { @@ -80,7 +81,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; private static readonly FixedFieldMap _responsesFixedFields = new(); @@ -88,8 +89,8 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _responsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument) @@ -147,18 +148,21 @@ private static OpenApiRequestBody CreateFormBody(ParsingContext context, List k.Name, - v => + v => { - var schema = v.Schema; + var schema = v.Schema.CreateShallowCopy(); schema.Description = v.Description; - schema.Extensions = v.Extensions; + if (schema is OpenApiSchema openApiSchema) + { + openApiSchema.Extensions = v.Extensions; + } return schema; }), - Required = new HashSet(formParameters.Where(p => p.Required).Select(p => p.Name)) + Required = new HashSet(formParameters.Where(static p => p.Required).Select(static p => p.Name), StringComparer.Ordinal) } }; @@ -173,8 +177,8 @@ private static OpenApiRequestBody CreateFormBody(ParsingContext context, List mediaType) }; - foreach (var value in formBody.Content.Values.Where(static x => x.Schema is not null && x.Schema.Properties.Any() && x.Schema.Type == null)) - value.Schema.Type = JsonSchemaType.Object; + foreach (var value in formBody.Content.Values.Where(static x => x.Schema is not null && x.Schema.Properties.Any() && x.Schema.Type == null).Select(static x => x.Schema).OfType()) + value.Type = JsonSchemaType.Object; return formBody; } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs index 2153d37d2..267ba24d7 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs @@ -106,7 +106,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _parameterPatternFields = new() { - {s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase) && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; @@ -147,7 +147,10 @@ private static void LoadParameterExamplesExtension(OpenApiParameter parameter, P private static OpenApiSchema GetOrCreateSchema(OpenApiParameter p) { - return p.Schema ??= new(); + return p.Schema switch { + OpenApiSchema schema => schema, + _ => (OpenApiSchema)(p.Schema = new OpenApiSchema()), + }; } private static void ProcessIn(OpenApiParameter o, ParseNode n, OpenApiDocument hostDocument) @@ -208,7 +211,7 @@ public static IOpenApiParameter LoadParameter(ParseNode node, bool loadRequestBo ParseMap(mapNode, parameter, _parameterFixedFields, _parameterPatternFields, doc: hostDocument); - var schema = node.Context.GetFromTempStorage("schema"); + var schema = node.Context.GetFromTempStorage("schema"); if (schema != null) { parameter.Schema = schema; diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs index 84f79cc16..b1e0da7a8 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathItemDeserializer.cs @@ -34,7 +34,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))}, }; public static OpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs index a048316d5..30d1df8a9 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiPathsDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -17,8 +18,8 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith("/", StringComparison.OrdinalIgnoreCase), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs index d730c8227..514ed0b44 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiResponseDeserializer.cs @@ -42,7 +42,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _responsePatternFields = new() { - {s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase) && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; @@ -74,7 +74,7 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P ?? context.GetFromTempStorage>(TempStorageKeys.GlobalProduces) ?? context.DefaultContentType ?? new List { "application/octet-stream" }; - var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response); + var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response); var examples = context.GetFromTempStorage>(TempStorageKeys.Examples, response) ?? new Dictionary(); @@ -171,7 +171,7 @@ private static void LoadExample(OpenApiResponse response, string mediaType, Pars { mediaTypeObject = new() { - Schema = node.Context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response) + Schema = node.Context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response) }; response.Content.Add(mediaType, mediaTypeObject); } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs index 78453f9d2..42575e394 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSchemaDeserializer.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System.Collections.Generic; @@ -7,6 +7,8 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Models.References; +using Microsoft.OpenApi.Models.Interfaces; +using System; namespace Microsoft.OpenApi.Reader.V2 { @@ -153,10 +155,10 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new PatternFieldMap { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("schema"); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs index 4dfdbba16..7b47ff6c5 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; namespace Microsoft.OpenApi.Reader.V2 @@ -21,7 +23,7 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, foreach (var property in mapNode) { var scheme = LoadSecuritySchemeByReference( - mapNode.Context, + hostDocument, property.Name); var scopes = property.Value.CreateSimpleList((n2, p) => n2.GetScalarValue(), hostDocument); @@ -41,21 +43,11 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, return securityRequirement; } - private static OpenApiSecurityScheme LoadSecuritySchemeByReference( - ParsingContext context, + private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference( + OpenApiDocument openApiDocument, string schemeName) { - var securitySchemeObject = new OpenApiSecurityScheme - { - UnresolvedReference = true, - Reference = new() - { - Id = schemeName, - Type = ReferenceType.SecurityScheme - } - }; - - return securitySchemeObject; + return new OpenApiSecuritySchemeReference(schemeName, openApiDocument); } } } diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs index 43151c15a..0dc329f43 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiSecuritySchemeDeserializer.cs @@ -1,9 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader.ParseNodes; namespace Microsoft.OpenApi.Reader.V2 @@ -77,10 +78,10 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; - public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) { // Reset the local variables every time this method is called. // TODO: Change _flow to a tempStorage variable to make the deserializer thread-safe. diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs index 23614029a..809dccacd 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiTagDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -31,7 +32,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs index 0e90a4633..83505670d 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2Deserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; @@ -98,7 +99,7 @@ private static (string, string) GetReferenceIdAndExternalResource(string pointer { var refSegments = pointer.Split('/'); var refId = refSegments.Last(); - var isExternalResource = !refSegments.First().StartsWith("#"); + var isExternalResource = !refSegments.First().StartsWith("#", StringComparison.OrdinalIgnoreCase); string externalResource = isExternalResource ? $"{refSegments.First()}/{refSegments[1].TrimEnd('#')}" : null; diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2VersionService.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2VersionService.cs index c9e58b519..c4186bb25 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiV2VersionService.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiV2VersionService.cs @@ -161,7 +161,7 @@ public OpenApiReference ConvertToOpenApiReference(string reference, ReferenceTyp } else if (segments.Length == 2) { - if (reference.StartsWith("#")) + if (reference.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // "$ref": "#/definitions/Pet" try @@ -178,7 +178,7 @@ public OpenApiReference ConvertToOpenApiReference(string reference, ReferenceTyp // Where fragments point into a non-OpenAPI document, the id will be the complete fragment identifier var id = segments[1]; // $ref: externalSource.yaml#/Pet - if (id.StartsWith("/definitions/")) + if (id.StartsWith("/definitions/", StringComparison.Ordinal)) { var localSegments = id.Split('/'); var referencedType = GetReferenceTypeV2FromName(localSegments[1]); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs index 21c9be0fe..38acf840d 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs @@ -51,7 +51,7 @@ internal static partial class OpenApiV2Deserializer private static readonly PatternFieldMap _xmlPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs index adab9ccab..4ec9bfa3a 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiCallbackDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Expressions; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; @@ -21,8 +22,8 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _callbackPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; public static IOpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs index a5e3d082b..76cfc96d7 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiComponentsDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -29,7 +30,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _componentsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiComponents LoadComponents(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs index cc5058b52..7eab275c8 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiContactDeserializer.cs @@ -32,7 +32,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs index 842b75bf0..c07d28d46 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiDocumentDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -33,7 +34,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _openApiPatternFields = new PatternFieldMap { // We have no semantics to verify X- nodes, therefore treat them as just values. - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiDocument LoadOpenApi(RootNode rootNode) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs index 2345436dd..2d324745d 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiEncodingDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -47,7 +48,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _encodingPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiEncoding LoadEncoding(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs index 344565884..5ec2665a0 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiExampleDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; @@ -38,7 +39,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _examplePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiExample LoadExample(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs index a3f20bad0..0d8c25b05 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiExternalDocsDeserializer.cs @@ -31,7 +31,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _externalDocsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs index 8553c1b70..94350d429 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; @@ -68,7 +69,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs index dbe3a554c..48979439d 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiInfoDeserializer.cs @@ -44,7 +44,7 @@ internal static partial class OpenApiV3Deserializer public static readonly PatternFieldMap InfoPatternFields = new() { - {s => s.StartsWith("x-"), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs index d836c6e0f..4ecdce151 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiLicenseDeserializer.cs @@ -28,7 +28,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; internal static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs index 9744ea256..f85fb0328 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiLinkDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; @@ -42,7 +43,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _linkPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; public static IOpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs index b30dc88e0..6fd96b38d 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiMediaTypeDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; @@ -38,7 +39,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _mediaTypePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _mediaTypeAnyFields = new() diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs index 1a7f40c15..d60cf0aa5 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowDeserializer.cs @@ -35,7 +35,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _oAuthFlowPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlow LoadOAuthFlow(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs index e4e003f9c..892ec4701 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOAuthFlowsDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -25,7 +26,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _oAuthFlowsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlows LoadOAuthFlows(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs index 1ebb57880..e9712da98 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiOperationDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -72,7 +73,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs index c8660d899..7d2c5074b 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; @@ -88,7 +89,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _parameterPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _parameterAnyFields = new() diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs index 4d5815794..baaf5babc 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathItemDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; @@ -40,7 +41,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs index e28a9d569..ef27f5d94 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiPathsDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -17,8 +18,8 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("/", StringComparison.OrdinalIgnoreCase), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs index 783f2869e..ac007d813 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiRequestBodyDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; @@ -35,7 +36,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _requestBodyPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiRequestBody LoadRequestBody(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs index a85ed5fe1..8e10c2e79 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponseDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; @@ -38,7 +39,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _responsePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs index 6d03fe86b..379811dda 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiResponsesDeserializer.cs @@ -18,8 +18,8 @@ internal static partial class OpenApiV3Deserializer public static readonly PatternFieldMap ResponsesPatternFields = new() { - {s => !s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, - {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs index bad6d04b8..25d68b477 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSchemaDeserializer.cs @@ -1,10 +1,12 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; +using System; using System.Collections.Generic; using System.Globalization; @@ -84,7 +86,14 @@ internal static partial class OpenApiV3Deserializer }, { "type", - (o, n, _) => o.Type = n.GetScalarValue().ToJsonSchemaType() + (o, n, _) => { + var type = n.GetScalarValue().ToJsonSchemaType(); + // so we don't loose the value from nullable + if (o.Type.HasValue) + o.Type |= type; + else + o.Type = type; + } }, { "allOf", @@ -137,7 +146,16 @@ internal static partial class OpenApiV3Deserializer }, { "nullable", - (o, n, _) => o.Nullable = bool.Parse(n.GetScalarValue()) + (o, n, _) => + { + if (bool.TryParse(n.GetScalarValue(), out var parsed) && parsed) + { + if (o.Type.HasValue) + o.Type |= JsonSchemaType.Null; + else + o.Type = JsonSchemaType.Null; + } + } }, { "discriminator", @@ -171,10 +189,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode(OpenApiConstants.Schema); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs index 73610713c..030f2ef34 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -21,7 +22,7 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, foreach (var property in mapNode) { - var scheme = LoadSecuritySchemeByReference(mapNode.Context, property.Name); + var scheme = LoadSecuritySchemeByReference(hostDocument, property.Name); var scopes = property.Value.CreateSimpleList((value, p) => value.GetScalarValue(), hostDocument); @@ -39,12 +40,11 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, return securityRequirement; } - private static OpenApiSecurityScheme LoadSecuritySchemeByReference( - ParsingContext context, + private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference( + OpenApiDocument openApiDocument, string schemeName) { - var securitySchemeObject = new OpenApiSecuritySchemeReference(schemeName, hostDocument: null); - return securitySchemeObject; + return new OpenApiSecuritySchemeReference(schemeName, openApiDocument); } } } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs index 18c4eae28..993279f1e 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiSecuritySchemeDeserializer.cs @@ -1,9 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -69,10 +70,10 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("securityScheme"); var pointer = mapNode.GetReferencePointer(); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs index 52ee335c0..4e4411625 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -31,7 +32,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _serverPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServer LoadServer(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs index 9436e62fe..3579a40b7 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiServerVariableDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -33,7 +34,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _serverVariablePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServerVariable LoadServerVariable(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs index e6efafae7..d67d54d7c 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiTagDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -31,7 +32,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs index cad424c50..67a9b0495 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3Deserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; @@ -148,7 +149,7 @@ private static RuntimeExpressionAnyWrapper LoadRuntimeExpressionAnyWrapper(Parse { var value = node.GetScalarValue(); - if (value != null && value.StartsWith("$")) + if (value != null && value.StartsWith("$", StringComparison.OrdinalIgnoreCase)) { return new() { @@ -190,7 +191,7 @@ private static (string, string) GetReferenceIdAndExternalResource(string pointer { var refSegments = pointer.Split('/'); var refId = refSegments.Last(); - var isExternalResource = !refSegments.First().StartsWith("#"); + var isExternalResource = !refSegments.First().StartsWith("#", StringComparison.OrdinalIgnoreCase); string externalResource = isExternalResource ? $"{refSegments.First()}/{refSegments[1].TrimEnd('#')}" : null; diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs index 372a8b26f..612c59dfb 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs @@ -102,7 +102,7 @@ public OpenApiReference ConvertToOpenApiReference( } else if (segments.Length == 2) { - if (reference.StartsWith("#")) + if (reference.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // "$ref": "#/components/schemas/Pet" try @@ -116,10 +116,10 @@ public OpenApiReference ConvertToOpenApiReference( } // Where fragments point into a non-OpenAPI document, the id will be the complete fragment identifier var id = segments[1]; - var openApiReference = new OpenApiReference(); + var isFragment = false; // $ref: externalSource.yaml#/Pet - if (id.StartsWith("/components/")) + if (id.StartsWith("/components/", StringComparison.Ordinal)) { var localSegments = segments[1].Split('/'); localSegments[2].TryGetEnumFromDisplayName(out var referencedType); @@ -136,7 +136,7 @@ public OpenApiReference ConvertToOpenApiReference( } id = localSegments[3]; } - else if (id.StartsWith("/paths/")) + else if (id.StartsWith("/paths/", StringComparison.Ordinal)) { var localSegments = segments[1].Split(_pathSeparator, StringSplitOptions.RemoveEmptyEntries); if (localSegments.Length == 2) @@ -152,12 +152,16 @@ public OpenApiReference ConvertToOpenApiReference( } else { - openApiReference.IsFragment = true; + isFragment = true; } - openApiReference.ExternalResource = segments[0]; - openApiReference.Type = type; - openApiReference.Id = id; + var openApiReference = new OpenApiReference + { + ExternalResource = segments[0], + Type = type, + Id = id, + IsFragment = isFragment, + }; return openApiReference; } @@ -179,11 +183,12 @@ public T LoadElement(ParseNode node, OpenApiDocument doc) where T : IOpenApiE /// public string GetReferenceScalarValues(MapNode mapNode, string scalarValue) { - if (mapNode.Any(static x => !"$ref".Equals(x.Name, StringComparison.OrdinalIgnoreCase))) + if (mapNode.Any(static x => !"$ref".Equals(x.Name, StringComparison.OrdinalIgnoreCase)) && + mapNode + .Where(x => x.Name.Equals(scalarValue)) + .Select(static x => x.Value) + .OfType().FirstOrDefault() is {} valueNode) { - var valueNode = mapNode.Where(x => x.Name.Equals(scalarValue)) - .Select(static x => x.Value).OfType().FirstOrDefault(); - return valueNode.GetScalarValue(); } diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs index 51b66d348..43245338d 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs @@ -41,7 +41,7 @@ internal static partial class OpenApiV3Deserializer private static readonly PatternFieldMap _xmlPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs index 49407e339..ac1a43998 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiCallbackDeserializer.cs @@ -20,8 +20,8 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _callbackPatternFields = new() { - {s => !s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, - {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.AddPathItem(RuntimeExpression.Build(p), LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; public static IOpenApiCallback LoadCallback(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs index c9dccde5d..2520692cd 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiComponentsDeserializer.cs @@ -31,7 +31,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _componentsPatternFields = new() { - {s => s.StartsWith("x-", StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiComponents LoadComponents(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs index 801eb2de9..be487e434 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiContactDeserializer.cs @@ -35,7 +35,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _contactPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiContact LoadContact(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs index 90e904f60..0302149f6 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -30,7 +31,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _discriminatorPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiDiscriminator LoadDiscriminator(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs index 0d1e08479..4f3a05fcc 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -31,7 +32,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _openApiPatternFields = new() { // We have no semantics to verify X- nodes, therefore treat them as just values. - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiDocument LoadOpenApi(RootNode rootNode) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs index 51a5b4ef6..d571a42d0 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiEncodingDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -51,7 +52,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _encodingPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiEncoding LoadEncoding(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs index f6511d8b9..49f7c3fd0 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiExampleDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; @@ -44,7 +45,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _examplePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiExample LoadExample(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs index 56dd2bc77..a5b06efff 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiExternalDocsDeserializer.cs @@ -33,7 +33,7 @@ internal static partial class OpenApiV31Deserializer new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))} }; public static OpenApiExternalDocs LoadExternalDocs(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs index 43a4f3292..2c23c70a4 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; @@ -82,7 +83,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _headerPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs index d3aed5511..86597b421 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiInfoDeserializer.cs @@ -59,7 +59,7 @@ internal static partial class OpenApiV31Deserializer public static readonly PatternFieldMap InfoPatternFields = new() { - {s => s.StartsWith("x-"), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, k, n, _) => o.AddExtension(k,LoadExtension(k, n))} }; public static OpenApiInfo LoadInfo(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs index 303f2f65a..7ef705095 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiLicenseDeserializer.cs @@ -35,7 +35,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _licensePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; internal static OpenApiLicense LoadLicense(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs index 3924a41c7..9fdea6e29 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiLinkDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; @@ -49,7 +50,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _linkPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; public static IOpenApiLink LoadLink(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs index a9024f9ed..2a46b4412 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiMediaTypeDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader.ParseNodes; @@ -43,7 +44,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _mediaTypePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _mediaTypeAnyFields = new AnyFieldMap diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs index 5b18caecf..3efc3ef5a 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowDeserializer.cs @@ -38,7 +38,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _oAuthFlowPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlow LoadOAuthFlow(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs index b20b96775..d472748f8 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOAuthFlowsDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -22,7 +23,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _oAuthFlowsPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiOAuthFlows LoadOAuthFlows(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs index 2d6c831e3..cb44bb438 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiOperationDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -90,7 +91,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _operationPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}, }; internal static OpenApiOperation LoadOperation(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs index cf5f5b294..35e1308cb 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; @@ -106,7 +107,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _parameterPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; private static readonly AnyFieldMap _parameterAnyFields = new AnyFieldMap diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs index ecaf88bf2..391a34bf6 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathItemDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; @@ -42,7 +43,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _pathItemPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiPathItem LoadPathItem(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs index c72394bf2..6e97b41ac 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiPathsDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -14,8 +15,8 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _pathsPatternFields = new() { - {s => s.StartsWith("/"), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith("/", StringComparison.OrdinalIgnoreCase), (o, k, n, t) => o.Add(k, LoadPathItem(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiPaths LoadPaths(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs index db6792a5f..fe786aa44 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiRequestBodyDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; @@ -38,7 +39,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _requestBodyPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiRequestBody LoadRequestBody(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs index a71fd5369..6d910761c 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponseDeserializer.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Extensions; +using System; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; @@ -43,7 +44,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _responsePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs index 228a0045e..50aad0d9a 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiResponsesDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -17,8 +18,8 @@ internal static partial class OpenApiV31Deserializer public static readonly PatternFieldMap ResponsesPatternFields = new() { - {s => !s.StartsWith("x-"), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => !s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, t) => o.Add(p, LoadResponse(n, t))}, + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiResponses LoadResponses(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs index 87ecc8f00..fcd97fca2 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs @@ -1,10 +1,12 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -236,10 +238,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _openApiSchemaPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode(OpenApiConstants.Schema); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs index b204c83d4..cddb97699 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -39,10 +40,9 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node, return securityRequirement; } - private static OpenApiSecurityScheme LoadSecuritySchemeByReference(string schemeName, OpenApiDocument hostDocument) + private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference(string schemeName, OpenApiDocument hostDocument) { - var securitySchemeObject = new OpenApiSecuritySchemeReference(schemeName, hostDocument); - return securitySchemeObject; + return new OpenApiSecuritySchemeReference(schemeName, hostDocument); } } } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs index b56352c22..2189f1179 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSecuritySchemeDeserializer.cs @@ -1,9 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -79,10 +80,10 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _securitySchemePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiSecurityScheme LoadSecurityScheme(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("securityScheme"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs index 2ae8ac340..b51a16f5d 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -37,7 +38,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _serverPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServer LoadServer(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs index 0c6e8b756..a3aaa141a 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiServerVariableDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -39,7 +40,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _serverVariablePatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiServerVariable LoadServerVariable(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs index f1b0065cc..aea4c9c43 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiTagDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; @@ -37,7 +38,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _tagPatternFields = new() { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiTag LoadTag(ParseNode n, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs index 7c3441eed..92e7770df 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Linq; using System.Text.Json.Nodes; using Microsoft.OpenApi.Any; @@ -113,7 +114,7 @@ private static RuntimeExpressionAnyWrapper LoadRuntimeExpressionAnyWrapper(Parse { var value = node.GetScalarValue(); - if (value != null && value.StartsWith("$")) + if (value != null && value.StartsWith("$", StringComparison.OrdinalIgnoreCase)) { return new RuntimeExpressionAnyWrapper { @@ -160,7 +161,7 @@ private static (string, string) GetReferenceIdAndExternalResource(string pointer var refSegments = pointer.Split('/'); string refId = !pointer.Contains('#') ? pointer : refSegments.Last(); - var isExternalResource = !refSegments.First().StartsWith("#"); + var isExternalResource = !refSegments.First().StartsWith("#", StringComparison.OrdinalIgnoreCase); string externalResource = null; if (isExternalResource && pointer.Contains('#')) { diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs index f564c37ab..bfaa82051 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs @@ -105,7 +105,7 @@ public OpenApiReference ConvertToOpenApiReference( } else if (segments.Length == 2) { - if (reference.StartsWith("#")) + if (reference.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // "$ref": "#/components/schemas/Pet" try @@ -121,7 +121,7 @@ public OpenApiReference ConvertToOpenApiReference( // Where fragments point into a non-OpenAPI document, the id will be the complete fragment identifier string id = segments[1]; // $ref: externalSource.yaml#/Pet - if (id.StartsWith("/components/")) + if (id.StartsWith("/components/", StringComparison.Ordinal)) { var localSegments = segments[1].Split('/'); localSegments[2].TryGetEnumFromDisplayName(out var referencedType); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs index 13870f341..0f821e9d2 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs @@ -51,7 +51,7 @@ internal static partial class OpenApiV31Deserializer private static readonly PatternFieldMap _xmlPatternFields = new PatternFieldMap { - {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} + {s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; public static OpenApiXml LoadXml(ParseNode node, OpenApiDocument hostDocument) diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs index 6fbcbcc4a..980aafb56 100644 --- a/src/Microsoft.OpenApi/Services/CopyReferences.cs +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -89,9 +89,9 @@ private void AddSchemaToComponents(OpenApiSchema schema, string referenceId = nu { EnsureComponentsExist(); EnsureSchemasExist(); - if (!Components.Schemas.ContainsKey(referenceId ?? schema.Reference.Id)) + if (!Components.Schemas.ContainsKey(referenceId)) { - Components.Schemas.Add(referenceId ?? schema.Reference.Id, schema); + Components.Schemas.Add(referenceId, schema); } } @@ -172,24 +172,20 @@ private void AddSecuritySchemeToComponents(OpenApiSecurityScheme securityScheme, { EnsureComponentsExist(); EnsureSecuritySchemesExist(); - if (!Components.SecuritySchemes.ContainsKey(referenceId ?? securityScheme.Reference.Id)) + if (!Components.SecuritySchemes.ContainsKey(referenceId)) { - Components.SecuritySchemes.Add(referenceId ?? securityScheme.Reference.Id, securityScheme); + Components.SecuritySchemes.Add(referenceId, securityScheme); } } /// - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { // This is needed to handle schemas used in Responses in components if (schema is OpenApiSchemaReference openApiSchemaReference) { AddSchemaToComponents(openApiSchemaReference.Target, openApiSchemaReference.Reference.Id); } - else if (schema.Reference != null) - { - AddSchemaToComponents(schema); - } base.Visit(schema); } @@ -200,7 +196,7 @@ private void EnsureComponentsExist() private void EnsureSchemasExist() { - _target.Components.Schemas ??= new Dictionary(); + _target.Components.Schemas ??= new Dictionary(); } private void EnsureParametersExist() @@ -240,7 +236,7 @@ private void EnsureLinksExist() private void EnsureSecuritySchemesExist() { - _target.Components.SecuritySchemes ??= new Dictionary(); + _target.Components.SecuritySchemes ??= new Dictionary(); } private void EnsurePathItemsExist() { diff --git a/src/Microsoft.OpenApi/Services/OpenApiUrlTreeNode.cs b/src/Microsoft.OpenApi/Services/OpenApiUrlTreeNode.cs index 1d306edfb..8a61772dd 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiUrlTreeNode.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiUrlTreeNode.cs @@ -41,7 +41,7 @@ public class OpenApiUrlTreeNode /// /// Flag indicating whether a node segment is a path parameter. /// - public bool IsParameter => Segment.StartsWith("{"); + public bool IsParameter => Segment.StartsWith("{", StringComparison.OrdinalIgnoreCase); /// /// The subdirectory of a relative path. @@ -144,7 +144,7 @@ public OpenApiUrlTreeNode Attach(string path, Utils.CheckArgumentNullOrEmpty(path); Utils.CheckArgumentNull(pathItem); - if (path.StartsWith(RootPathSegment)) + if (path.StartsWith(RootPathSegment, StringComparison.OrdinalIgnoreCase)) { // Remove leading slash path = path.Substring(1); diff --git a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs index b2eb9eab1..254528b41 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs @@ -230,9 +230,9 @@ public virtual void Visit(OpenApiExternalDocs externalDocs) } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiSchema schema) + public virtual void Visit(IOpenApiSchema schema) { } @@ -293,9 +293,9 @@ public virtual void Visit(OpenApiSecurityRequirement securityRequirement) } /// - /// Visits + /// Visits /// - public virtual void Visit(OpenApiSecurityScheme securityScheme) + public virtual void Visit(IOpenApiSecurityScheme securityScheme) { } diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index 41d7561ab..ae4430067 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -19,7 +19,7 @@ namespace Microsoft.OpenApi.Services public class OpenApiWalker { private readonly OpenApiVisitorBase _visitor; - private readonly Stack _schemaLoop = new(); + private readonly Stack _schemaLoop = new(); private readonly Stack _pathItemLoop = new(); /// @@ -864,11 +864,11 @@ internal void Walk(OpenApiEncoding encoding) } /// - /// Visits and child objects + /// Visits and child objects /// - internal void Walk(OpenApiSchema schema, bool isComponent = false) + internal void Walk(IOpenApiSchema schema, bool isComponent = false) { - if (schema == null || ProcessAsReference(schema, isComponent)) + if (schema == null || schema is IOpenApiReferenceHolder holder && ProcessAsReference(holder, isComponent)) { return; } @@ -1012,9 +1012,9 @@ internal void Walk(IList examples) } /// - /// Visits a list of and child objects + /// Visits a list of and child objects /// - internal void Walk(IList schemas) + internal void Walk(IList schemas) { if (schemas == null) { @@ -1146,9 +1146,9 @@ internal void Walk(OpenApiSecurityRequirement securityRequirement) } /// - /// Visits and child objects + /// Visits and child objects /// - internal void Walk(OpenApiSecurityScheme securityScheme, bool isComponent = false) + internal void Walk(IOpenApiSecurityScheme securityScheme, bool isComponent = false) { if (securityScheme == null) { diff --git a/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs b/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs index f92e6f322..ec368a6c0 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Services { @@ -165,16 +166,16 @@ public bool RegisterComponentForDocument(OpenApiDocument openApiDocument, T c var location = componentToRegister switch { - OpenApiSchema => baseUri + ReferenceType.Schema.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiParameter => baseUri + ReferenceType.Parameter.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiResponse => baseUri + ReferenceType.Response.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiRequestBody => baseUri + ReferenceType.RequestBody.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiLink => baseUri + ReferenceType.Link.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiCallback => baseUri + ReferenceType.Callback.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiPathItem => baseUri + ReferenceType.PathItem.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiExample => baseUri + ReferenceType.Example.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiHeader => baseUri + ReferenceType.Header.GetDisplayName() + ComponentSegmentSeparator + id, - OpenApiSecurityScheme => baseUri + ReferenceType.SecurityScheme.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiSchema => baseUri + ReferenceType.Schema.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiParameter => baseUri + ReferenceType.Parameter.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiResponse => baseUri + ReferenceType.Response.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiRequestBody => baseUri + ReferenceType.RequestBody.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiLink => baseUri + ReferenceType.Link.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiCallback => baseUri + ReferenceType.Callback.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiPathItem => baseUri + ReferenceType.PathItem.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiExample => baseUri + ReferenceType.Example.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiHeader => baseUri + ReferenceType.Header.GetDisplayName() + ComponentSegmentSeparator + id, + IOpenApiSecurityScheme => baseUri + ReferenceType.SecurityScheme.GetDisplayName() + ComponentSegmentSeparator + id, _ => throw new ArgumentException($"Invalid component type {componentToRegister.GetType().Name}"), }; diff --git a/src/Microsoft.OpenApi/Services/ReferenceHostDocumentSetter.cs b/src/Microsoft.OpenApi/Services/ReferenceHostDocumentSetter.cs index 146c8941d..c660d21bd 100644 --- a/src/Microsoft.OpenApi/Services/ReferenceHostDocumentSetter.cs +++ b/src/Microsoft.OpenApi/Services/ReferenceHostDocumentSetter.cs @@ -21,10 +21,7 @@ public ReferenceHostDocumentSetter(OpenApiDocument currentDocument) /// public override void Visit(IOpenApiReferenceHolder referenceHolder) { - if (referenceHolder.Reference != null) - { - referenceHolder.Reference.HostDocument = _currentDocument; - } + referenceHolder.Reference?.EnsureHostDocumentIsSet(_currentDocument); } } } diff --git a/src/Microsoft.OpenApi/Utils.cs b/src/Microsoft.OpenApi/Utils.cs index b025af8e7..094361bb9 100644 --- a/src/Microsoft.OpenApi/Utils.cs +++ b/src/Microsoft.OpenApi/Utils.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace Microsoft.OpenApi @@ -19,7 +20,11 @@ internal static class Utils /// The input parameter name. /// The input value. internal static T CheckArgumentNull( +#if NET5_0_OR_GREATER + [NotNull] T value, +#else T value, +#endif [CallerArgumentExpression(nameof(value))] string parameterName = "") { return value ?? throw new ArgumentNullException(parameterName, $"Value cannot be null: {parameterName}"); @@ -32,7 +37,11 @@ internal static T CheckArgumentNull( /// The input parameter name. /// The input value. internal static string CheckArgumentNullOrEmpty( +#if NET5_0_OR_GREATER + [NotNull] string value, +#else string value, +#endif [CallerArgumentExpression(nameof(value))] string parameterName = "") { return string.IsNullOrWhiteSpace(value) ? throw new ArgumentNullException(parameterName, $"Value cannot be null or empty: {parameterName}") : value; diff --git a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs index 0e1251d2e..784f06172 100644 --- a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs +++ b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs @@ -108,7 +108,7 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(IOpenApiParameter parameter) => Validate(parameter); /// - public override void Visit(OpenApiSchema schema) => Validate(schema); + public override void Visit(IOpenApiSchema schema) => Validate(schema); /// public override void Visit(OpenApiServer server) => Validate(server); @@ -135,7 +135,7 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(OpenApiServerVariable serverVariable) => Validate(serverVariable); /// - public override void Visit(OpenApiSecurityScheme securityScheme) => Validate(securityScheme); + public override void Visit(IOpenApiSecurityScheme securityScheme) => Validate(securityScheme); /// public override void Visit(OpenApiSecurityRequirement securityRequirement) => Validate(securityRequirement); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs index 3509d797f..545f68f85 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -22,7 +23,7 @@ public static class OpenApiExtensibleRules (context, item) => { context.Enter("extensions"); - foreach (var extensible in item.Extensions.Keys.Where(static x => !x.StartsWith("x-", StringComparison.OrdinalIgnoreCase))) + foreach (var extensible in item.Extensions.Keys.Where(static x => !x.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase))) { context.CreateError(nameof(ExtensionNameMustStartWithXDash), string.Format(SRResource.Validation_ExtensionNameMustBeginWithXDash, extensible, context.PathString)); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs index 1d38af4ce..03661401c 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs @@ -47,7 +47,7 @@ public static class OpenApiNonDefaultRules /// /// Validate the data matches with the given data type. /// - public static ValidationRule SchemaMismatchedDataType => + public static ValidationRule SchemaMismatchedDataType => new(nameof(SchemaMismatchedDataType), (context, schema) => { @@ -91,7 +91,7 @@ private static void ValidateMismatchedDataType(IValidationContext context, string ruleName, JsonNode example, IDictionary examples, - OpenApiSchema schema) + IOpenApiSchema schema) { // example context.Enter("example"); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs index 054c79c6b..b954c96b6 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -16,14 +18,14 @@ public static class OpenApiSchemaRules /// /// Validates Schema Discriminator /// - public static ValidationRule ValidateSchemaDiscriminator => + public static ValidationRule ValidateSchemaDiscriminator => new(nameof(ValidateSchemaDiscriminator), (context, schema) => { // discriminator context.Enter("discriminator"); - if (schema.Reference != null && schema.Discriminator != null) + if (schema is not null && schema.Discriminator != null) { var discriminatorName = schema.Discriminator?.PropertyName; @@ -31,7 +33,7 @@ public static class OpenApiSchemaRules { context.CreateError(nameof(ValidateSchemaDiscriminator), string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator, - schema.Reference.Id, discriminatorName)); + schema is OpenApiSchemaReference { Reference: not null} schemaReference ? schemaReference.Reference.Id : string.Empty, discriminatorName)); } } @@ -44,7 +46,7 @@ public static class OpenApiSchemaRules /// The parent schema. /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate /// between other schemas which may satisfy the payload description. - public static bool ValidateChildSchemaAgainstDiscriminator(OpenApiSchema schema, string discriminatorName) + public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema, string discriminatorName) { if (!schema.Required?.Contains(discriminatorName) ?? false) { @@ -77,7 +79,7 @@ public static bool ValidateChildSchemaAgainstDiscriminator(OpenApiSchema schema, /// between other schemas which may satisfy the payload description. /// The child schema. /// - public static bool TraverseSchemaElements(string discriminatorName, IList childSchema) + public static bool TraverseSchemaElements(string discriminatorName, IList childSchema) { foreach (var childItem in childSchema) { diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index 61b9d3a0c..63ca4d05e 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -5,6 +5,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Validations.Rules { @@ -44,7 +45,7 @@ public static void ValidateDataTypeMismatch( IValidationContext context, string ruleName, JsonNode value, - OpenApiSchema schema) + IOpenApiSchema schema) { if (schema == null) { @@ -56,11 +57,10 @@ public static void ValidateDataTypeMismatch( var type = schema.Type.ToIdentifier(); var format = schema.Format; - var nullable = schema.Nullable; // Before checking the type, check first if the schema allows null. // If so and the data given is also null, this is allowed for any type. - if (nullable && valueKind is JsonValueKind.Null) + if ((schema.Type.Value & JsonSchemaType.Null) is JsonSchemaType.Null && valueKind is JsonValueKind.Null) { return; } diff --git a/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs b/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs index 7f525d642..aaa160548 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiYamlWriter.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.IO; namespace Microsoft.OpenApi.Writers @@ -189,7 +190,7 @@ public override void WriteValue(string value) WriteChompingIndicator(value); // Write indentation indicator when it starts with spaces - if (value.StartsWith(" ")) + if (value.StartsWith(" ", StringComparison.OrdinalIgnoreCase)) { Writer.Write(IndentationString.Length); } diff --git a/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs b/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs index 708aa7237..22388b076 100644 --- a/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs +++ b/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs @@ -148,7 +148,7 @@ internal static string GetYamlCompatibleString(this string input) // wrap the string in single quote. // http://www.yaml.org/spec/1.2/spec.html#style/flow/plain if (_yamlPlainStringForbiddenCombinations.Any(fc => input.Contains(fc)) || - _yamlIndicators.Any(i => input.StartsWith(i)) || + _yamlIndicators.Any(i => input.StartsWith(i, StringComparison.Ordinal)) || _yamlPlainStringForbiddenTerminals.Any(i => input.EndsWith(i)) || input.Trim() != input) { @@ -199,7 +199,7 @@ internal static string GetJsonCompatibleString(this string value) internal static bool IsHexadecimalNotation(string input) { - return input.StartsWith("0x") && int.TryParse(input.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _); + return input.StartsWith("0x", StringComparison.Ordinal) && int.TryParse(input.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _); } } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs index abf7232d1..da6d8c61e 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs @@ -58,21 +58,23 @@ public void RemoveAnyOfAndOneOfFromSchema() var walker = new OpenApiWalker(powerShellFormatter); walker.Walk(openApiDocument); - var testSchema = openApiDocument.Components?.Schemas?["TestSchema"]; - var averageAudioDegradationProperty = testSchema?.Properties["averageAudioDegradation"]; - var defaultPriceProperty = testSchema?.Properties["defaultPrice"]; + Assert.NotNull(openApiDocument.Components); + Assert.NotNull(openApiDocument.Components.Schemas); + var testSchema = openApiDocument.Components.Schemas["TestSchema"]; + var averageAudioDegradationProperty = testSchema.Properties["averageAudioDegradation"]; + var defaultPriceProperty = testSchema.Properties["defaultPrice"]; // Assert Assert.NotNull(openApiDocument.Components); Assert.NotNull(openApiDocument.Components.Schemas); Assert.NotNull(testSchema); - Assert.Null(averageAudioDegradationProperty?.AnyOf); - Assert.Equal(JsonSchemaType.Number, averageAudioDegradationProperty?.Type); - Assert.Equal("float", averageAudioDegradationProperty?.Format); - Assert.True(averageAudioDegradationProperty?.Nullable); - Assert.Null(defaultPriceProperty?.OneOf); - Assert.Equal(JsonSchemaType.Number, defaultPriceProperty?.Type); - Assert.Equal("double", defaultPriceProperty?.Format); + Assert.Null(averageAudioDegradationProperty.AnyOf); + Assert.Equal(JsonSchemaType.Number | JsonSchemaType.Null, averageAudioDegradationProperty.Type); + Assert.Equal("float", averageAudioDegradationProperty.Format); + Assert.Equal(JsonSchemaType.Null, averageAudioDegradationProperty.Type & JsonSchemaType.Null); + Assert.Null(defaultPriceProperty.OneOf); + Assert.Equal(JsonSchemaType.Number, defaultPriceProperty.Type); + Assert.Equal("double", defaultPriceProperty.Format); Assert.NotNull(testSchema.AdditionalProperties); } @@ -122,10 +124,10 @@ private static OpenApiDocument GetSampleOpenApiDocument() "application/json", new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -149,32 +151,31 @@ private static OpenApiDocument GetSampleOpenApiDocument() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { { "TestSchema", new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "averageAudioDegradation", new OpenApiSchema { - AnyOf = new List + AnyOf = new List { - new() { Type = JsonSchemaType.Number }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number | JsonSchemaType.Null }, + new OpenApiSchema() { Type = JsonSchemaType.String } }, Format = "float", - Nullable = true } }, { "defaultPrice", new OpenApiSchema { - OneOf = new List + OneOf = new List { - new() { Type = JsonSchemaType.Number, Format = "double" }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "double" }, + new OpenApiSchema() { Type = JsonSchemaType.String } } } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index ca4416ae6..a3494ba13 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -129,7 +129,7 @@ public void CreateFilteredDocumentUsingPredicateFromRequestUrl() Name = "id", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs index 0d25c7704..3f81c71a3 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs @@ -87,7 +87,7 @@ public static OpenApiDocument CreateOpenApiDocument() Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -106,7 +106,7 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -127,7 +127,7 @@ public static OpenApiDocument CreateOpenApiDocument() Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -152,7 +152,7 @@ public static OpenApiDocument CreateOpenApiDocument() Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -171,7 +171,7 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -191,7 +191,7 @@ public static OpenApiDocument CreateOpenApiDocument() Name = "period", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -219,25 +219,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Title = "Collection of user", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "value", new OpenApiSchema { Type = JsonSchemaType.Array, - Items = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.user" - } - } } } } @@ -273,14 +265,6 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.user" - } - } } } } @@ -325,7 +309,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Query, Required = true, Description = "Select properties to be returned", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array } @@ -344,14 +328,6 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.message" - } - } } } } @@ -380,7 +356,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Path, Required = true, Description = "key: id of administrativeUnit", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -399,16 +375,9 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { - AnyOf = new List - { - new() - { - Type = JsonSchemaType.String - } - }, - Nullable = true + Type = JsonSchemaType.String | JsonSchemaType.Null } } } @@ -463,25 +432,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Title = "Collection of hostSecurityProfile", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "value", new OpenApiSchema { Type = JsonSchemaType.Array, - Items = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "microsoft.graph.networkInterface" - } - } } } } @@ -513,7 +474,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Path, Description = "key: id of call", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -561,7 +522,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Path, Description = "key: id of group", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -578,7 +539,7 @@ public static OpenApiDocument CreateOpenApiDocument() In = ParameterLocation.Path, Description = "key: id of event", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -602,13 +563,17 @@ public static OpenApiDocument CreateOpenApiDocument() applicationJsonMediaType, new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { - Type = JsonSchemaType.Array, - Reference = new() + Properties = new Dictionary { - Type = ReferenceType.Schema, - Id = "microsoft.graph.event" + { + "value", + new OpenApiSchema + { + Type = JsonSchemaType.Array, + } + } } } } @@ -643,21 +608,20 @@ public static OpenApiDocument CreateOpenApiDocument() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { { "microsoft.graph.networkInterface", new OpenApiSchema { Title = "networkInterface", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { { "description", new OpenApiSchema { - Type = JsonSchemaType.String, + Type = JsonSchemaType.String | JsonSchemaType.Null, Description = "Description of the NIC (e.g. Ethernet adapter, Wireless LAN adapter Local Area Connection <#>, etc.).", - Nullable = true } } } @@ -726,6 +690,11 @@ public static OpenApiDocument CreateOpenApiDocument() document.Paths[communicationsCallsKeepAlivePath].Operations[OperationType.Post].Tags!.Add(new OpenApiTagReference("communications.Actions", document)); document.Paths[eventsDeltaPath].Operations[OperationType.Get].Tags!.Add(new OpenApiTagReference("groups.Functions", document)); document.Paths[refPath].Operations[OperationType.Get].Tags!.Add(new OpenApiTagReference("applications.directoryObject", document)); + ((OpenApiSchema)document.Paths[usersPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.user", document); + document.Paths[usersByIdPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema = new OpenApiSchemaReference("microsoft.graph.user", document); + document.Paths[messagesByIdPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema = new OpenApiSchemaReference("microsoft.graph.message", document); + ((OpenApiSchema)document.Paths[securityProfilesPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.networkInterface", document); + ((OpenApiSchema)document.Paths[eventsDeltaPath].Operations[OperationType.Get].Responses!["200"].Content[applicationJsonMediaType].Schema!.Properties["value"]).Items = new OpenApiSchemaReference("microsoft.graph.event", document); return document; } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs index 2b079ffb8..68ecbe33e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs @@ -30,7 +30,6 @@ public async Task LoadingDocumentWithResolveAllReferencesShouldLoadDocumentIntoW BaseUrl = new("file://c:\\") }; - // Todo: this should be ReadAsync var stream = new MemoryStream(); var doc = """ openapi: 3.0.0 diff --git a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs index 8440e8df4..3edc9ac67 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs @@ -37,7 +37,7 @@ public async Task LoadParameterReference() In = ParameterLocation.Query, Description = "number of items to skip", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -56,13 +56,13 @@ public async Task LoadSecuritySchemeReference() var reference = new OpenApiSecuritySchemeReference("api_key_sample", result.Document); // Assert - reference.Should().BeEquivalentTo( + Assert.Equivalent( new OpenApiSecurityScheme { Type = SecuritySchemeType.ApiKey, Name = "api_key", In = ParameterLocation.Header - }, options => options.Excluding(x => x.Reference) + }, reference ); } @@ -92,41 +92,23 @@ public async Task LoadResponseAndSchemaReference() var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); var reference = new OpenApiResponseReference("GeneralError", result.Document); - // Assert - Assert.Equivalent( - new OpenApiResponse + var expected = new OpenApiResponse { Description = "General Error", Content = { ["application/json"] = new() { - Schema = new() - { - Description = "Sample description", - Required = new HashSet {"name" }, - Properties = { - ["name"] = new() - { - Type = JsonSchemaType.String - }, - ["tag"] = new() - { - Type = JsonSchemaType.String - } - }, - - Reference = new() - { - Type = ReferenceType.Schema, - Id = "SampleObject2", - HostDocument = result.Document - } - } + Schema = new OpenApiSchemaReference("SampleObject2") } } - }, reference - ); + }; + + ((OpenApiSchemaReference)expected.Content["application/json"].Schema).Reference.EnsureHostDocumentIsSet(result.Document); + var actual = reference.Target; + + // Assert + Assert.Equivalent(expected, actual); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index 5993d4e2c..136c46892 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -10,6 +10,7 @@ using FluentAssertions.Equivalency; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Xunit; @@ -73,12 +74,12 @@ public void ParseDocumentWithDifferentCultureShouldSucceed(string culture) { Schemas = { - ["sampleSchema"] = new() + ["sampleSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["sampleProperty"] = new() + ["sampleProperty"] = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = (decimal)100.54, @@ -106,7 +107,7 @@ public async Task ShouldParseProducesInAnyOrder() var okSchema = new OpenApiSchema { - Properties = new Dictionary + Properties = new Dictionary { { "id", new OpenApiSchema { @@ -119,7 +120,7 @@ public async Task ShouldParseProducesInAnyOrder() var errorSchema = new OpenApiSchema { - Properties = new Dictionary + Properties = new Dictionary { { "code", new OpenApiSchema { @@ -142,7 +143,7 @@ public async Task ShouldParseProducesInAnyOrder() var okMediaType = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("Item", result.Document) @@ -276,7 +277,7 @@ public async Task ShouldAssignSchemaToAllResponses() var responses = result.Document.Paths["/items"].Operations[OperationType.Get].Responses; foreach (var response in responses) { - var targetSchema = response.Key == "200" ? successSchema : errorSchema; + var targetSchema = response.Key == "200" ? (IOpenApiSchema)successSchema : errorSchema; var json = response.Value.Content["application/json"]; Assert.NotNull(json); @@ -294,9 +295,11 @@ public async Task ShouldAllowComponentsThatJustContainAReference() // Act var actual = (await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "ComponentRootReference.json"))).Document; var schema1 = actual.Components.Schemas["AllPets"]; - Assert.False(schema1.UnresolvedReference); - var schema2 = actual.ResolveReferenceTo(schema1.Reference); - if (schema2.UnresolvedReference && schema1.Reference.Id == schema2.Reference.Id) + var schema1Reference = Assert.IsType(schema1); + Assert.False(schema1Reference.UnresolvedReference); + var schema2 = actual.ResolveReferenceTo(schema1Reference.Reference); + Assert.IsType(schema2); + if (string.IsNullOrEmpty(schema1Reference.Reference.Id) || schema1Reference.UnresolvedReference) { // detected a cycle - this code gets triggered Assert.Fail("A cycle should not be detected"); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs index cc15d8427..1b1187a42 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiHeaderTests.cs @@ -34,7 +34,7 @@ public void ParseHeaderWithDefaultShouldSucceed() header.Should().BeEquivalentTo( new OpenApiHeader { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", @@ -63,7 +63,7 @@ public void ParseHeaderWithEnumShouldSucceed() header.Should().BeEquivalentTo( new OpenApiHeader { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs index ce7382b65..13339332a 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs @@ -39,7 +39,7 @@ public class OpenApiOperationTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -72,7 +72,7 @@ public class OpenApiOperationTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -86,7 +86,7 @@ public class OpenApiOperationTests { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -216,10 +216,10 @@ public void ParseOperationWithResponseExamplesShouldSucceed() { ["application/json"] = new OpenApiMediaType() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -234,10 +234,10 @@ public void ParseOperationWithResponseExamplesShouldSucceed() }, ["application/xml"] = new OpenApiMediaType() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs index 1b6300faf..aa11d5137 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiParameterTests.cs @@ -57,7 +57,7 @@ public void ParsePathParameterShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -86,10 +86,10 @@ public void ParseQueryParameterShouldSucceed() Name = "id", Description = "ID of the object to fetch", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -121,7 +121,7 @@ public void ParseParameterWithNullLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -150,7 +150,7 @@ public void ParseParameterWithNoLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -204,7 +204,7 @@ public void ParseParameterWithUnknownLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -233,7 +233,7 @@ public void ParseParameterWithDefaultShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", @@ -260,7 +260,7 @@ public void ParseParameterWithEnumShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float", diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs index a86d84bdd..412a74dde 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs @@ -27,10 +27,10 @@ public class OpenApiPathItemTests In = ParameterLocation.Path, Description = "ID of pet to use", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -53,7 +53,7 @@ public class OpenApiPathItemTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -65,17 +65,17 @@ public class OpenApiPathItemTests { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -89,17 +89,17 @@ public class OpenApiPathItemTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -148,7 +148,7 @@ public class OpenApiPathItemTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -159,7 +159,7 @@ public class OpenApiPathItemTests In = ParameterLocation.Path, Description = "Name of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -171,22 +171,22 @@ public class OpenApiPathItemTests { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String }, - ["skill"] = new() + ["skill"] = new OpenApiSchema() { Description = "Updated skill of the pet", Type = JsonSchemaType.String @@ -200,22 +200,22 @@ public class OpenApiPathItemTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String }, - ["skill"] = new() + ["skill"] = new OpenApiSchema() { Description = "Updated skill of the pet", Type = JsonSchemaType.String @@ -249,11 +249,8 @@ public class OpenApiPathItemTests public void ParseBasicPathItemWithFormDataShouldSucceed() { // Arrange - MapNode node; - using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicPathItemWithFormData.yaml"))) - { - node = TestHelper.CreateYamlMapNode(stream); - } + using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicPathItemWithFormData.yaml")); + var node = TestHelper.CreateYamlMapNode(stream); // Act var pathItem = OpenApiV2Deserializer.LoadPathItem(node, new()); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs index 1b36921d7..781b272e1 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiSchemaTests.cs @@ -13,6 +13,7 @@ using FluentAssertions.Equivalency; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Readers.Tests.V2Tests { @@ -108,7 +109,7 @@ public void PropertiesReferenceShouldWork() var targetSchema = new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["prop1"] = new OpenApiSchema() { @@ -121,7 +122,7 @@ public void PropertiesReferenceShouldWork() var referenceSchema = new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["propA"] = new OpenApiSchemaReference(referenceId, workingDocument), } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.ParseDocumentWith31PropertiesWorks.verified.txt b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.ParseDocumentWith31PropertiesWorks.verified.txt index 3392a4bb8..fa7dd54e4 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.ParseDocumentWith31PropertiesWorks.verified.txt +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.ParseDocumentWith31PropertiesWorks.verified.txt @@ -5,7 +5,6 @@ info: description: A sample API demonstrating OpenAPI 3.1 features license: name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0.html identifier: Apache-2.0 version: 2.0.0 summary: Sample OpenAPI 3.1 API with the latest features @@ -93,6 +92,11 @@ components: - 'null' - object description: Dynamic attributes for the pet + securitySchemes: + api_key: + type: apiKey + name: api_key + in: header security: - api_key: [ ] webhooks: diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs index cda7e35c3..6f955e62f 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs @@ -11,8 +11,8 @@ using Microsoft.OpenApi.Writers; using Xunit; using VerifyXunit; -using VerifyTests; using Microsoft.OpenApi.Models.Interfaces; +using System; namespace Microsoft.OpenApi.Readers.Tests.V31Tests { @@ -38,7 +38,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() { Schemas = { - ["petSchema"] = new() + ["petSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -46,42 +46,42 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPetSchema"] = new() + ["newPetSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -115,10 +115,10 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -130,7 +130,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -146,7 +146,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -154,7 +154,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -212,9 +212,9 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["petSchema"] = new() + ["petSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -222,42 +222,42 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPetSchema"] = new() + ["newPetSchema"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -289,10 +289,10 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -304,7 +304,7 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -419,7 +419,7 @@ public async Task ParseDocumentWithPatternPropertiesInSchemaWorks() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["prop1"] = new OpenApiSchema { @@ -434,7 +434,7 @@ public async Task ParseDocumentWithPatternPropertiesInSchemaWorks() Type = JsonSchemaType.String } }, - PatternProperties = new Dictionary + PatternProperties = new Dictionary { ["^x-.*$"] = new OpenApiSchema { @@ -539,5 +539,11 @@ public async Task ParseDocumentWith31PropertiesWorks() // Assert await Verifier.Verify(actual); } + + [Fact] + public void ParseEmptyMemoryStreamThrowsAnArgumentException() + { + Assert.Throws(() => OpenApiDocument.Load(new MemoryStream())); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs index abcaa9df6..555b71c54 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs @@ -9,6 +9,7 @@ using FluentAssertions; using FluentAssertions.Equivalency; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Tests; using Microsoft.OpenApi.Writers; @@ -42,7 +43,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() Schema = "https://json-schema.org/draft/2020-12/schema", Description = "A representation of a person, company, organization, or place", Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["fruits"] = new OpenApiSchema { @@ -57,7 +58,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() Type = JsonSchemaType.Array } }, - Definitions = new Dictionary + Definitions = new Dictionary { ["veggie"] = new OpenApiSchema { @@ -67,7 +68,7 @@ public async Task ParseBasicV31SchemaShouldSucceed() "veggieName", "veggieLike" }, - Properties = new Dictionary + Properties = new Dictionary { ["veggieName"] = new OpenApiSchema { @@ -139,13 +140,11 @@ public void TestSchemaCopyConstructorWithTypeArrayWorks() }; // Act - var schemaWithArrayCopy = new OpenApiSchema(schemaWithTypeArray); + var schemaWithArrayCopy = schemaWithTypeArray.CreateShallowCopy() as OpenApiSchema; schemaWithArrayCopy.Type = JsonSchemaType.String; - var simpleSchemaCopy = new OpenApiSchema(simpleSchema) - { - Type = JsonSchemaType.String | JsonSchemaType.Null - }; + var simpleSchemaCopy = simpleSchema.CreateShallowCopy() as OpenApiSchema; + simpleSchemaCopy.Type = JsonSchemaType.String | JsonSchemaType.Null; // Assert Assert.NotEqual(schemaWithTypeArray.Type, schemaWithArrayCopy.Type); @@ -165,9 +164,9 @@ public async Task ParseV31SchemaShouldSucceed() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["one"] = new() + ["one"] = new OpenApiSchema() { Description = "type array", Type = JsonSchemaType.Integer | JsonSchemaType.String @@ -189,29 +188,29 @@ public async Task ParseAdvancedV31SchemaShouldSucceed() var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["one"] = new() + ["one"] = new OpenApiSchema() { Description = "type array", Type = JsonSchemaType.Integer | JsonSchemaType.String }, - ["two"] = new() + ["two"] = new OpenApiSchema() { Description = "type 'null'", Type = JsonSchemaType.Null }, - ["three"] = new() + ["three"] = new OpenApiSchema() { Description = "type array including 'null'", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["four"] = new() + ["four"] = new OpenApiSchema() { Description = "array with no items", Type = JsonSchemaType.Array }, - ["five"] = new() + ["five"] = new OpenApiSchema() { Description = "singular example", Type = JsonSchemaType.String, @@ -220,37 +219,37 @@ public async Task ParseAdvancedV31SchemaShouldSucceed() "exampleValue" } }, - ["six"] = new() + ["six"] = new OpenApiSchema() { Description = "exclusiveMinimum true", V31ExclusiveMinimum = 10 }, - ["seven"] = new() + ["seven"] = new OpenApiSchema() { Description = "exclusiveMinimum false", Minimum = 10 }, - ["eight"] = new() + ["eight"] = new OpenApiSchema() { Description = "exclusiveMaximum true", V31ExclusiveMaximum = 20 }, - ["nine"] = new() + ["nine"] = new OpenApiSchema() { Description = "exclusiveMaximum false", Maximum = 20 }, - ["ten"] = new() + ["ten"] = new OpenApiSchema() { Description = "nullable string", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["eleven"] = new() + ["eleven"] = new OpenApiSchema() { Description = "x-nullable string", Type = JsonSchemaType.String | JsonSchemaType.Null }, - ["twelve"] = new() + ["twelve"] = new OpenApiSchema() { Description = "file/binary" } @@ -293,7 +292,7 @@ public void CloningSchemaWithExamplesAndEnumsShouldSucceed() Enum = [1, 2, 3] }; - var clone = new OpenApiSchema(schema); + var clone = schema.CreateShallowCopy() as OpenApiSchema; clone.Examples.Add(4); clone.Enum.Add(4); clone.Default = 6; diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiDocument/documentWith31Properties.yaml b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiDocument/documentWith31Properties.yaml index 35e5ccf80..e3d1b6cf5 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiDocument/documentWith31Properties.yaml +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiDocument/documentWith31Properties.yaml @@ -7,7 +7,6 @@ info: license: name: Apache 2.0 identifier: Apache-2.0 # SPDX license identifier, a new 3.1 feature to define an API's SPDX license expression - url: https://www.apache.org/licenses/LICENSE-2.0.html # JSON Schema 2020-12 feature jsonSchemaDialect: "https://json-schema.org/draft/2020-12/schema" @@ -89,6 +88,11 @@ paths: - name $dynamicAnchor: "addressDef" components: + securitySchemes: + api_key: + type: apiKey + name: api_key + in: header schemas: Pet: $id: 'https://example.com/schemas/pet.json' diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs index 4476d23a8..5aabe43d3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs @@ -94,7 +94,7 @@ public async Task ParseCallbackWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -144,7 +144,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -180,7 +180,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -215,7 +215,7 @@ public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 1b8f26c64..ea287db5e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -26,13 +26,14 @@ namespace Microsoft.OpenApi.Readers.Tests.V3Tests public class OpenApiDocumentTests { private const string SampleFolderPath = "V3Tests/Samples/OpenApiDocument/"; + private const string codacyApi = "https://api.codacy.com/api/api-docs/swagger.yaml"; public OpenApiDocumentTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); } - private static async Task CloneAsync(T element) where T : IOpenApiSerializable + private static async Task CloneAsync(T element) where T : class, IOpenApiSerializable { using var stream = new MemoryStream(); var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); @@ -49,23 +50,6 @@ private static async Task CloneAsync(T element) where T : IOpenApiSerializ return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, new(), out var _); } - private static async Task CloneSecuritySchemeAsync(OpenApiSecurityScheme element) - { - using var stream = new MemoryStream(); - var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(streamWriter, new OpenApiJsonWriterSettings() - { - InlineLocalReferences = true - }); - element.SerializeAsV3(writer); - await writer.FlushAsync(); - stream.Position = 0; - - using var streamReader = new StreamReader(stream); - var result = await streamReader.ReadToEndAsync(); - return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, new(), out var _); - } - [Fact] public void ParseDocumentFromInlineStringShouldSucceed() { @@ -205,9 +189,9 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet1"] = new() + ["pet1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -215,48 +199,48 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -264,14 +248,14 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -331,10 +315,10 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -346,7 +330,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -362,7 +346,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -370,7 +354,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = petSchema @@ -474,7 +458,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -534,7 +518,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -591,9 +575,9 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() var components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet1"] = new() + ["pet1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -601,48 +585,48 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -650,21 +634,21 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } } }, }, - SecuritySchemes = new Dictionary + SecuritySchemes = new Dictionary { ["securitySchemeName1"] = new OpenApiSecurityScheme { @@ -681,51 +665,28 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() }; // Create a clone of the schema to avoid modifying things in components. - var petSchema = await CloneAsync(components.Schemas["pet1"]); - petSchema.Reference = new() - { - Id = "pet1", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; + var petSchemaSource = Assert.IsType(components.Schemas["pet1"]); + var petSchema = await CloneAsync(petSchemaSource); + Assert.IsType(petSchema); + var petSchemaReference = new OpenApiSchemaReference("pet1"); - var newPetSchema = await CloneAsync(components.Schemas["newPet"]); + var newPetSchemaSource = Assert.IsType(components.Schemas["newPet"]); + var newPetSchema = await CloneAsync(newPetSchemaSource); + Assert.IsType(newPetSchema); + var newPetSchemaReference = new OpenApiSchemaReference("newPet"); - newPetSchema.Reference = new() - { - Id = "newPet", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; + var errorModelSchemaSource = Assert.IsType(components.Schemas["errorModel"]); + var errorModelSchema = await CloneAsync(errorModelSchemaSource); + Assert.IsType(errorModelSchema); + var errorModelSchemaReference = new OpenApiSchemaReference("errorModel"); - var errorModelSchema = await CloneAsync(components.Schemas["errorModel"]); + var tagReference1 = new OpenApiTagReference("tagName1"); - errorModelSchema.Reference = new() - { - Id = "errorModel", - Type = ReferenceType.Schema, - HostDocument = actual.Document - }; - - var tagReference1 = new OpenApiTagReference("tagName1", null); - - var tagReference2 = new OpenApiTagReference("tagName2", null); + var tagReference2 = new OpenApiTagReference("tagName2"); - var securityScheme1 = await CloneSecuritySchemeAsync(components.SecuritySchemes["securitySchemeName1"]); - - securityScheme1.Reference = new OpenApiReference - { - Id = "securitySchemeName1", - Type = ReferenceType.SecurityScheme - }; + Assert.IsType(components.SecuritySchemes["securitySchemeName1"]); - var securityScheme2 = await CloneSecuritySchemeAsync(components.SecuritySchemes["securitySchemeName2"]); - - securityScheme2.Reference = new OpenApiReference - { - Id = "securitySchemeName2", - Type = ReferenceType.SecurityScheme - }; + Assert.IsType(components.SecuritySchemes["securitySchemeName2"]); var expected = new OpenApiDocument { @@ -778,10 +739,10 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -793,7 +754,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -809,18 +770,18 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = petSchema + Items = petSchemaReference } }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = petSchema + Items = petSchemaReference } } } @@ -832,7 +793,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -843,7 +804,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -866,7 +827,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = newPetSchema + Schema = newPetSchemaReference } } }, @@ -879,7 +840,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference }, } }, @@ -890,7 +851,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -901,7 +862,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -910,8 +871,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { new OpenApiSecurityRequirement { - [securityScheme1] = new List(), - [securityScheme2] = new List + [new OpenApiSecuritySchemeReference("securitySchemeName1")] = new List(), + [new OpenApiSecuritySchemeReference("securitySchemeName2")] = new List { "scope1", "scope2" @@ -938,7 +899,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -954,11 +915,11 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["application/json"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference }, ["application/xml"] = new OpenApiMediaType { - Schema = petSchema + Schema = petSchemaReference } } }, @@ -969,7 +930,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -980,7 +941,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -998,7 +959,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -1018,7 +979,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } }, @@ -1029,7 +990,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { ["text/html"] = new OpenApiMediaType { - Schema = errorModelSchema + Schema = errorModelSchemaReference } } } @@ -1056,8 +1017,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { new OpenApiSecurityRequirement { - [securityScheme1] = new List(), - [securityScheme2] = new List + [new OpenApiSecuritySchemeReference("securitySchemeName1")] = new List(), + [new OpenApiSecuritySchemeReference("securitySchemeName2")] = new List { "scope1", "scope2", @@ -1066,11 +1027,11 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() } } }; - - tagReference1.Reference.HostDocument = expected; - tagReference2.Reference.HostDocument = expected; + expected.RegisterComponents(); + expected.SetReferenceHostDocument(); actual.Document.Should().BeEquivalentTo(expected, options => options + .IgnoringCyclicReferences() .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Reference) .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Reference.HostDocument) .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Target) @@ -1105,8 +1066,7 @@ public async Task GlobalSecurityRequirementShouldReferenceSecurityScheme() var securityRequirement = result.Document.SecurityRequirements[0]; - securityRequirement.Keys.First().Should().BeEquivalentTo(result.Document.Components.SecuritySchemes.First().Value, - options => options.Excluding(x => x.Reference)); + Assert.Equivalent(result.Document.Components.SecuritySchemes.First().Value, securityRequirement.Keys.First()); } [Fact] @@ -1127,7 +1087,7 @@ public async Task HeaderParameterShouldAllowExample() Style = ParameterStyle.Simple, Explode = true, Example = "99391c7e-ad88-49ec-a2ad-99ddcb1f7721", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "uuid" @@ -1160,7 +1120,7 @@ public async Task HeaderParameterShouldAllowExample() } } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "uuid" @@ -1183,7 +1143,6 @@ public async Task ParseDocumentWithReferencedSecuritySchemeWorks() var securityScheme = result.Document.Components.SecuritySchemes["OAuth2"]; // Assert - Assert.False(securityScheme.UnresolvedReference); Assert.NotNull(securityScheme.Flows); } @@ -1231,7 +1190,7 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() In = ParameterLocation.Query, Description = "Limit the number of pets returned", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32", @@ -1257,7 +1216,7 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() Summary = "Returns all pets", Parameters = [ - new OpenApiParameterReference(parameter, "LimitParameter"), + new OpenApiParameterReference("LimitParameter"), ], Responses = new OpenApiResponses() } @@ -1272,8 +1231,12 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() } } }; + expected.RegisterComponents(); + expected.SetReferenceHostDocument(); - var expectedSerializedDoc = @"openapi: 3.0.4 + var expectedSerializedDoc = +""" +openapi: 3.0.4 info: title: Pet Store with Referenceable Parameter version: 1.0.0 @@ -1293,7 +1256,8 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() schema: type: integer format: int32 - default: 10"; + default: 10 +"""; using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "minifiedPetStore.yaml")); @@ -1303,7 +1267,6 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() var outputDoc = (await doc.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0)).MakeLineBreaksEnvironmentNeutral(); var expectedParam = expected.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; var expectedParamReference = Assert.IsType(expectedParam); - expectedParamReference.Reference.HostDocument = doc; var actualParamReference = Assert.IsType(actualParam); @@ -1397,12 +1360,16 @@ public async Task ParseDocumentWithEmptyPathsSucceeds() public async Task ParseDocumentWithExampleReferencesPasses() { // Act & Assert: Ensure no NullReferenceException is thrown - Func act = async () => - { - await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "docWithExampleReferences.yaml")); - }; + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "docWithExampleReferences.yaml")); + Assert.Empty(result.Diagnostic.Errors); + } - await act.Should().NotThrowAsync(); + [Fact] + public async Task ParseDocumentWithNonStandardMIMETypePasses() + { + // Act & Assert: Ensure NotSupportedException is not thrown for non-standard MIME type: text/x-yaml + var result = await OpenApiDocument.LoadAsync(codacyApi); + Assert.NotNull(result.Document); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs index c103db5d8..bee674bfc 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs @@ -52,7 +52,7 @@ public async Task ParseAdvancedEncodingShouldSucceed() new OpenApiHeader() { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs index e10c78a25..2905266fc 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs @@ -35,7 +35,7 @@ public async Task ParseMediaTypeWithExampleShouldSucceed() new OpenApiMediaType { Example = 5, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -66,7 +66,7 @@ public async Task ParseMediaTypeWithExamplesShouldSucceed() Value = 7.5 } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs index 22167e0ee..1dd24a128 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs @@ -27,8 +27,7 @@ public async Task OperationWithSecurityRequirementShouldReferenceSecurityScheme( var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "securedOperation.yaml")); var securityScheme = result.Document.Paths["/"].Operations[OperationType.Get].Security[0].Keys.First(); - securityScheme.Should().BeEquivalentTo(result.Document.Components.SecuritySchemes.First().Value, - options => options.Excluding(x => x.Reference)); + Assert.Equivalent(result.Document.Components.SecuritySchemes.First().Value, securityScheme); } [Fact] @@ -56,7 +55,7 @@ public async Task ParseOperationWithParameterWithNoLocationShouldSucceed() Name = "username", Description = "The user name for login", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -67,7 +66,7 @@ public async Task ParseOperationWithParameterWithNoLocationShouldSucceed() Description = "The password for login in clear text", In = ParameterLocation.Query, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs index 17411a859..efdb87110 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs @@ -41,7 +41,7 @@ public async Task ParsePathParameterShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -62,10 +62,10 @@ public async Task ParseQueryParameterShouldSucceed() Name = "id", Description = "ID of the object to fetch", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -87,10 +87,10 @@ public async Task ParseQueryParameterWithObjectTypeShouldSucceed() { In = ParameterLocation.Query, Name = "freeForm", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -118,7 +118,7 @@ public async Task ParseQueryParameterWithObjectTypeAndContentShouldSucceed() { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = @@ -128,11 +128,11 @@ public async Task ParseQueryParameterWithObjectTypeAndContentShouldSucceed() }, Properties = { - ["lat"] = new() + ["lat"] = new OpenApiSchema() { Type = JsonSchemaType.Number }, - ["long"] = new() + ["long"] = new OpenApiSchema() { Type = JsonSchemaType.Number } @@ -159,10 +159,10 @@ public async Task ParseHeaderParameterShouldSucceed() Required = true, Style = ParameterStyle.Simple, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64", @@ -185,7 +185,7 @@ public async Task ParseParameterWithNullLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -209,7 +209,7 @@ public async Task ParseParameterWithNoLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -233,7 +233,7 @@ public async Task ParseParameterWithUnknownLocationShouldSucceed() Name = "username", Description = "username to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -255,7 +255,7 @@ public async Task ParseParameterWithExampleShouldSucceed() Description = "username to fetch", Required = true, Example = (float)5.0, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -288,7 +288,7 @@ public async Task ParseParameterWithExamplesShouldSucceed() Value = (float) 7.5 } }, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "float" @@ -308,7 +308,7 @@ public void ParseParameterWithReferenceWorks() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchema @@ -343,7 +343,7 @@ public void ParseParameterWithReferenceWorks() OperationId = "findPets", Parameters = [ - new OpenApiParameterReference (parameter, "tagsParameter"), + new OpenApiParameterReference("tagsParameter"), ], } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs index 8d94822ef..2fd230a19 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs @@ -165,7 +165,7 @@ public void ParseDictionarySchemaShouldSucceed() new OpenApiSchema { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -199,12 +199,12 @@ public void ParseBasicSchemaWithExampleShouldSucceed() Type = JsonSchemaType.Object, Properties = { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -245,18 +245,18 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() { Schemas = { - ["ErrorModel"] = new() + ["ErrorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Minimum = 100, Maximum = 600 }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -267,7 +267,7 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() "code" } }, - ["ExtendedErrorModel"] = new() + ["ExtendedErrorModel"] = new OpenApiSchema() { AllOf = { @@ -278,7 +278,7 @@ public async Task ParseBasicSchemaWithReferenceShouldSucceed() Required = {"rootCause"}, Properties = { - ["rootCause"] = new() + ["rootCause"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -302,7 +302,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() { Schemas = { - ["Pet"] = new() + ["Pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Discriminator = new() @@ -311,11 +311,11 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() }, Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["petType"] = new() + ["petType"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -326,7 +326,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() "petType" } }, - ["Cat"] = new() + ["Cat"] = new OpenApiSchema() { Description = "A representation of a cat", AllOf = @@ -338,7 +338,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() Required = {"huntingSkill"}, Properties = { - ["huntingSkill"] = new() + ["huntingSkill"] = new OpenApiSchema() { Type = JsonSchemaType.String, Description = "The measured skill for hunting", @@ -354,7 +354,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() } } }, - ["Dog"] = new() + ["Dog"] = new OpenApiSchema() { Description = "A representation of a dog", AllOf = @@ -366,7 +366,7 @@ public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() Required = {"packSize"}, Properties = { - ["packSize"] = new() + ["packSize"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32", diff --git a/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs b/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs index c41bd6e98..dead3b27c 100644 --- a/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs +++ b/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs @@ -15,45 +15,45 @@ public class OpenApiTypeMapperTests { new object[] { typeof(int), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32" } }, new object[] { typeof(decimal), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double" } }, - new object[] { typeof(decimal?), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double", Nullable = true } }, - new object[] { typeof(bool?), new OpenApiSchema { Type = JsonSchemaType.Boolean, Nullable = true } }, + new object[] { typeof(decimal?), new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" } }, + new object[] { typeof(bool?), new OpenApiSchema { Type = JsonSchemaType.Boolean | JsonSchemaType.Null } }, new object[] { typeof(Guid), new OpenApiSchema { Type = JsonSchemaType.String, Format = "uuid" } }, - new object[] { typeof(Guid?), new OpenApiSchema { Type = JsonSchemaType.String, Format = "uuid", Nullable = true } }, + new object[] { typeof(Guid?), new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "uuid" } }, new object[] { typeof(uint), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32" } }, new object[] { typeof(long), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64" } }, - new object[] { typeof(long?), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true } }, + new object[] { typeof(long?), new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int64" } }, new object[] { typeof(ulong), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64" } }, new object[] { typeof(string), new OpenApiSchema { Type = JsonSchemaType.String } }, new object[] { typeof(double), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double" } }, - new object[] { typeof(float?), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "float", Nullable = true } }, - new object[] { typeof(byte?), new OpenApiSchema { Type = JsonSchemaType.String, Format = "byte", Nullable = true } }, - new object[] { typeof(int?), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true } }, - new object[] { typeof(uint?), new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true } }, - new object[] { typeof(DateTimeOffset?), new OpenApiSchema { Type = JsonSchemaType.String, Format = "date-time", Nullable = true } }, - new object[] { typeof(double?), new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double", Nullable = true } }, - new object[] { typeof(char?), new OpenApiSchema { Type = JsonSchemaType.String, Nullable = true } }, + new object[] { typeof(float?), new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "float" } }, + new object[] { typeof(byte?), new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "byte" } }, + new object[] { typeof(int?), new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32" } }, + new object[] { typeof(uint?), new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32" } }, + new object[] { typeof(DateTimeOffset?), new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "date-time" } }, + new object[] { typeof(double?), new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" } }, + new object[] { typeof(char?), new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null } }, new object[] { typeof(DateTimeOffset), new OpenApiSchema { Type = JsonSchemaType.String, Format = "date-time" } } }; public static IEnumerable OpenApiDataTypes => new List { - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32", Nullable = false}, typeof(int) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32", Nullable = true}, typeof(int?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64", Nullable = false}, typeof(long) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64", Nullable = true}, typeof(long?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int32" }, typeof(int) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int32"}, typeof(int?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = "int64" }, typeof(long) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = "int64"}, typeof(long?) }, new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "decimal"}, typeof(decimal) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = null, Nullable = false}, typeof(long) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = null, Nullable = true}, typeof(long?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = null, Nullable = false}, typeof(double) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = null, Nullable = true}, typeof(double?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "decimal", Nullable = true}, typeof(decimal?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double", Nullable = true}, typeof(double?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.String, Format = "date-time", Nullable = true}, typeof(DateTimeOffset?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.String, Format = "char", Nullable = true}, typeof(char?) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.String, Format = "uuid", Nullable = true}, typeof(Guid?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer, Format = null }, typeof(long) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Integer | JsonSchemaType.Null, Format = null}, typeof(long?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = null }, typeof(double) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = null}, typeof(double?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "decimal"}, typeof(decimal?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double"}, typeof(double?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "date-time"}, typeof(DateTimeOffset?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "char"}, typeof(char?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, Format = "uuid"}, typeof(Guid?) }, new object[] { new OpenApiSchema { Type = JsonSchemaType.String }, typeof(string) }, new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "double" }, typeof(double) }, - new object[] { new OpenApiSchema { Type = JsonSchemaType.Number, Format = "float", Nullable = true }, typeof(float?) }, + new object[] { new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "float" }, typeof(float?) }, new object[] { new OpenApiSchema { Type = JsonSchemaType.String, Format = "date-time" }, typeof(DateTimeOffset) } }; diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index b50e38c05..76373a2e0 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs index c84788ba8..fc232fa3a 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiCallbackTests.cs @@ -16,7 +16,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiCallbackTests { - public static OpenApiCallback AdvancedCallback = new() + private static OpenApiCallback AdvancedCallback => new() { PathItems = { @@ -34,7 +34,7 @@ public class OpenApiCallbackTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } @@ -54,9 +54,9 @@ public class OpenApiCallbackTests } }; - public static OpenApiCallbackReference CallbackProxy = new(ReferencedCallback, "simpleHook"); + private static OpenApiCallbackReference CallbackProxy => new("simpleHook"); - public static OpenApiCallback ReferencedCallback = new() + private static OpenApiCallback ReferencedCallback => new() { PathItems = { @@ -74,7 +74,7 @@ public class OpenApiCallbackTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs index 45448aa60..379dc0c4f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiComponentsTests.cs @@ -16,17 +16,17 @@ public class OpenApiComponentsTests { public static OpenApiComponents AdvancedComponents = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 @@ -34,9 +34,9 @@ public class OpenApiComponentsTests } } }, - SecuritySchemes = new Dictionary + SecuritySchemes = new Dictionary { - ["securityScheme1"] = new() + ["securityScheme1"] = new OpenApiSecurityScheme() { Description = "description1", Type = SecuritySchemeType.OAuth2, @@ -53,7 +53,7 @@ public class OpenApiComponentsTests } } }, - ["securityScheme2"] = new() + ["securityScheme2"] = new OpenApiSecurityScheme() { Description = "description1", Type = SecuritySchemeType.OpenIdConnect, @@ -65,33 +65,33 @@ public class OpenApiComponentsTests public static OpenApiComponents AdvancedComponentsWithReference = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, ["property3"] = new OpenApiSchemaReference("schema2", null) } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer } } }, }, - SecuritySchemes = new Dictionary + SecuritySchemes = new Dictionary { - ["securityScheme1"] = new() + ["securityScheme1"] = new OpenApiSecurityScheme() { Description = "description1", Type = SecuritySchemeType.OAuth2, @@ -107,23 +107,13 @@ public class OpenApiComponentsTests AuthorizationUrl = new("https://example.com/api/oauth") } }, - Reference = new() - { - Type = ReferenceType.SecurityScheme, - Id = "securityScheme1" - } }, - ["securityScheme2"] = new() + ["securityScheme2"] = new OpenApiSecurityScheme() { Description = "description1", Type = SecuritySchemeType.OpenIdConnect, Scheme = OpenApiConstants.Bearer, OpenIdConnectUrl = new("https://example.com/openIdConnect"), - Reference = new() - { - Type = ReferenceType.SecurityScheme, - Id = "securityScheme2" - } } } }; @@ -132,22 +122,22 @@ public class OpenApiComponentsTests public static OpenApiComponents BrokenComponents = new() { - Schemas = new Dictionary + Schemas = new Dictionary { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.String }, ["schema2"] = null, ["schema3"] = null, - ["schema4"] = new() + ["schema4"] = new OpenApiSchema() { Type = JsonSchemaType.String, - AllOf = new List + AllOf = new List { null, null, - new() + new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -163,12 +153,12 @@ public class OpenApiComponentsTests Schemas = { ["schema1"] = new OpenApiSchemaReference("schema2", null), - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -181,23 +171,23 @@ public class OpenApiComponentsTests { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -216,11 +206,11 @@ public class OpenApiComponentsTests public static OpenApiComponents ComponentsWithPathItem = new OpenApiComponents { - Schemas = new Dictionary() + Schemas = new Dictionary() { ["schema1"] = new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["property2"] = new OpenApiSchema() { @@ -230,9 +220,9 @@ public class OpenApiComponentsTests } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["property2"] = new OpenApiSchema() { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 5c905f238..3716a0b32 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -34,12 +34,12 @@ public OpenApiDocumentTests() Schemas = { ["schema1"] = new OpenApiSchemaReference("schema2", null), - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String, Annotations = new Dictionary { { "key1", "value" } } @@ -53,30 +53,25 @@ public OpenApiDocumentTests() { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String, Annotations = new Dictionary { { "key1", "value" } } } }, Annotations = new Dictionary { { "key1", "value" } }, - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schema1" - } }, - ["schema2"] = new() + ["schema2"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -90,13 +85,8 @@ public OpenApiDocumentTests() { Schemas = { - ["schema1"] = new() + ["schema1"] = new OpenApiSchema() { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schema1" - } } } }; @@ -133,9 +123,9 @@ public OpenApiDocumentTests() public static readonly OpenApiComponents AdvancedComponentsWithReference = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet"] = new() + ["pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -143,48 +133,48 @@ public OpenApiDocumentTests() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -192,14 +182,14 @@ public OpenApiDocumentTests() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -208,12 +198,12 @@ public OpenApiDocumentTests() } }; - public static OpenApiSchema PetSchemaWithReference = AdvancedComponentsWithReference.Schemas["pet"]; + public static OpenApiSchema PetSchemaWithReference = AdvancedComponentsWithReference.Schemas["pet"] as OpenApiSchema; - public static OpenApiSchema NewPetSchemaWithReference = AdvancedComponentsWithReference.Schemas["newPet"]; + public static OpenApiSchema NewPetSchemaWithReference = AdvancedComponentsWithReference.Schemas["newPet"] as OpenApiSchema; public static OpenApiSchema ErrorModelSchemaWithReference = - AdvancedComponentsWithReference.Schemas["errorModel"]; + AdvancedComponentsWithReference.Schemas["errorModel"] as OpenApiSchema; public static readonly OpenApiDocument AdvancedDocumentWithReference = new OpenApiDocument { @@ -261,10 +251,10 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -276,7 +266,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -292,7 +282,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchemaWithReference @@ -300,7 +290,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchemaWithReference @@ -404,7 +394,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -464,7 +454,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -510,9 +500,9 @@ public OpenApiDocumentTests() public static readonly OpenApiComponents AdvancedComponents = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { - ["pet"] = new() + ["pet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -520,48 +510,48 @@ public OpenApiDocumentTests() "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["newPet"] = new() + ["newPet"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet { "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, } }, - ["errorModel"] = new() + ["errorModel"] = new OpenApiSchema() { Type = JsonSchemaType.Object, Required = new HashSet @@ -569,14 +559,14 @@ public OpenApiDocumentTests() "code", "message" }, - Properties = new Dictionary + Properties = new Dictionary { - ["code"] = new() + ["code"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" }, - ["message"] = new() + ["message"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -585,11 +575,11 @@ public OpenApiDocumentTests() } }; - public static readonly OpenApiSchema PetSchema = AdvancedComponents.Schemas["pet"]; + public static readonly OpenApiSchema PetSchema = AdvancedComponents.Schemas["pet"] as OpenApiSchema; - public static readonly OpenApiSchema NewPetSchema = AdvancedComponents.Schemas["newPet"]; + public static readonly OpenApiSchema NewPetSchema = AdvancedComponents.Schemas["newPet"] as OpenApiSchema; - public static readonly OpenApiSchema ErrorModelSchema = AdvancedComponents.Schemas["errorModel"]; + public static readonly OpenApiSchema ErrorModelSchema = AdvancedComponents.Schemas["errorModel"] as OpenApiSchema; public OpenApiDocument AdvancedDocument = new OpenApiDocument { @@ -637,10 +627,10 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -652,7 +642,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -668,7 +658,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -676,7 +666,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -780,7 +770,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -840,7 +830,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -923,7 +913,7 @@ public OpenApiDocumentTests() }, Components = new OpenApiComponents { - Schemas = new Dictionary + Schemas = new Dictionary { ["Pet"] = new OpenApiSchema() { @@ -931,18 +921,18 @@ public OpenApiDocumentTests() { "id", "name" }, - Properties = new Dictionary + Properties = new Dictionary { - ["id"] = new() + ["id"] = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" }, - ["name"] = new() + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String }, - ["tag"] = new() + ["tag"] = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -984,7 +974,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "The first operand", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Extensions = new Dictionary @@ -1003,7 +993,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "The second operand", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Extensions = new Dictionary @@ -1026,7 +1016,7 @@ public OpenApiDocumentTests() { ["application/json"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1096,10 +1086,10 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "tags to filter by", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -1111,7 +1101,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Query, Description = "maximum number of results to return", Required = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" @@ -1127,7 +1117,7 @@ public OpenApiDocumentTests() { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1135,7 +1125,7 @@ public OpenApiDocumentTests() }, ["application/xml"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = PetSchema @@ -1239,7 +1229,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to fetch", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -1299,7 +1289,7 @@ public OpenApiDocumentTests() In = ParameterLocation.Path, Description = "ID of pet to delete", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" @@ -1561,14 +1551,6 @@ public async Task SerializeDocumentWithReferenceButNoComponents() { ["application/json"] = new OpenApiMediaType { - Schema = new() - { - Reference = new() - { - Id = "test", - Type = ReferenceType.Schema - } - } } } } @@ -1578,6 +1560,7 @@ public async Task SerializeDocumentWithReferenceButNoComponents() } } }; + document.Paths["/"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema = new OpenApiSchemaReference("test", document); // Act var actual = await document.SerializeAsync(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json); @@ -1738,7 +1721,7 @@ public async Task SerializeV2DocumentWithNonArraySchemaTypeDoesNotWriteOutCollec new OpenApiParameter { In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -1806,10 +1789,10 @@ public async Task SerializeV2DocumentWithStyleAsNullDoesNotWriteOutStyleValue() { Name = "id", In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -1825,7 +1808,7 @@ public async Task SerializeV2DocumentWithStyleAsNullDoesNotWriteOutStyleValue() { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiExampleTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiExampleTests.cs index d1e2cd8f5..fd59b4250 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiExampleTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiExampleTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiExampleTests { - public static OpenApiExample AdvancedExample = new() + private static OpenApiExample AdvancedExample => new() { Value = new JsonObject { @@ -57,8 +57,8 @@ public class OpenApiExampleTests } }; - public static OpenApiExampleReference OpenApiExampleReference = new(ReferencedExample, "example1"); - public static OpenApiExample ReferencedExample = new() + private static OpenApiExampleReference OpenApiExampleReference => new("example1"); + private static OpenApiExample ReferencedExample => new() { Value = new JsonObject { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs index e368c587b..afda460f7 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiHeaderTests.cs @@ -15,22 +15,22 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiHeaderTests { - public static OpenApiHeader AdvancedHeader = new() + private static OpenApiHeader AdvancedHeader => new() { Description = "sampleHeader", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" } }; - public static OpenApiHeaderReference OpenApiHeaderReference = new(ReferencedHeader, "example1"); + private static OpenApiHeaderReference OpenApiHeaderReference => new("example1"); - public static OpenApiHeader ReferencedHeader = new() + private static OpenApiHeader ReferencedHeader => new() { Description = "sampleHeader", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int32" diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiLinkTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiLinkTests.cs index e97fbb6b8..a6b4bc500 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiLinkTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiLinkTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiLinkTests { - public static readonly OpenApiLink AdvancedLink = new() + private static OpenApiLink AdvancedLink => new() { OperationId = "operationId1", Parameters = @@ -42,8 +42,8 @@ public class OpenApiLinkTests } }; - public static readonly OpenApiLinkReference LinkReference = new(ReferencedLink, "example1"); - public static readonly OpenApiLink ReferencedLink = new() + private static OpenApiLinkReference LinkReference => new("example1"); + private static OpenApiLink ReferencedLink => new() { OperationId = "operationId1", Parameters = diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs index df6b069ed..af22284b9 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.Collections.Generic; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; @@ -47,7 +48,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -58,28 +59,14 @@ public class OpenApiOperationTests }, Responses = new() { - ["200"] = new OpenApiResponseReference(new OpenApiResponse() - { - Content = new Dictionary - { - ["application/json"] = new() - { - Schema = new() - { - Type = JsonSchemaType.Number, - Minimum = 5, - Maximum = 10 - } - } - } - }, "response1"), + ["200"] = new OpenApiResponseReference("response1"), ["400"] = new OpenApiResponse() { Content = new Dictionary { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -100,7 +87,7 @@ public class OpenApiOperationTests Annotations = new Dictionary { { "key1", "value1" }, { "key2", 2 } }, }; - private static readonly OpenApiOperation _advancedOperationWithTagsAndSecurity = new() + private static OpenApiOperation _advancedOperationWithTagsAndSecurity => new() { Tags = new List { @@ -135,7 +122,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -146,28 +133,14 @@ public class OpenApiOperationTests }, Responses = new() { - ["200"] = new OpenApiResponseReference(new OpenApiResponse() - { - Content = new Dictionary - { - ["application/json"] = new() - { - Schema = new() - { - Type = JsonSchemaType.Number, - Minimum = 5, - Maximum = 10 - } - } - } - }, "response1"), + ["200"] = new OpenApiResponseReference("response1"), ["400"] = new OpenApiResponse() { Content = new Dictionary { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Number, Minimum = 5, @@ -181,8 +154,8 @@ public class OpenApiOperationTests { new() { - [new OpenApiSecuritySchemeReference("securitySchemeId1", hostDocument: null)] = new List(), - [new OpenApiSecuritySchemeReference("securitySchemeId2", hostDocument: null)] = new List + [new OpenApiSecuritySchemeReference("securitySchemeId1", __advancedOperationWithTagsAndSecurity_supportingDocument)] = new List(), + [new OpenApiSecuritySchemeReference("securitySchemeId2", __advancedOperationWithTagsAndSecurity_supportingDocument)] = new List { "scopeName1", "scopeName2" @@ -198,6 +171,34 @@ public class OpenApiOperationTests } } }; + private static OpenApiDocument __advancedOperationWithTagsAndSecurity_supportingDocument + { + get + { + var document = new OpenApiDocument() + { + Components = new() + { + SecuritySchemes = new Dictionary + { + ["securitySchemeId1"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.ApiKey, + Name = "apiKeyName1", + In = ParameterLocation.Header, + }, + ["securitySchemeId2"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OpenIdConnect, + OpenIdConnectUrl = new("http://example.com"), + } + } + } + }; + document.RegisterComponents(); + return document; + } + } private static readonly OpenApiOperation _operationWithFormData = new() @@ -213,7 +214,7 @@ public class OpenApiOperationTests In = ParameterLocation.Path, Description = "ID of pet that needs to be updated", Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -225,16 +226,16 @@ public class OpenApiOperationTests { ["application/x-www-form-urlencoded"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -248,16 +249,16 @@ public class OpenApiOperationTests }, ["multipart/form-data"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Properties = { - ["name"] = new() + ["name"] = new OpenApiSchema() { Description = "Updated name of the pet", Type = JsonSchemaType.String }, - ["status"] = new() + ["status"] = new OpenApiSchema() { Description = "Updated status of the pet", Type = JsonSchemaType.String @@ -455,9 +456,7 @@ public async Task SerializeAdvancedOperationWithTagAndSecurityAsV3JsonWorks() var actual = await _advancedOperationWithTagsAndSecurity.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -475,9 +474,7 @@ public async Task SerializeBasicOperationAsV2JsonWorks() var actual = await _basicOperation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -554,9 +551,7 @@ public async Task SerializeOperationWithFormDataAsV3JsonWorks() var actual = await _operationWithFormData.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -610,9 +605,7 @@ public async Task SerializeOperationWithFormDataAsV2JsonWorks() var actual = await _operationWithFormData.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -679,9 +672,7 @@ public async Task SerializeOperationWithBodyAsV2JsonWorks() var actual = await _operationWithBody.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -760,9 +751,7 @@ public async Task SerializeAdvancedOperationWithTagAndSecurityAsV2JsonWorks() var actual = await _advancedOperationWithTagsAndSecurity.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -785,9 +774,7 @@ public async Task SerializeOperationWithNullCollectionAsV2JsonWorks() var actual = await operation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs index edec7bbd8..da0c00d44 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using VerifyXunit; @@ -18,20 +19,20 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiParameterTests { - public static OpenApiParameter BasicParameter = new() + private static OpenApiParameter BasicParameter => new() { Name = "name1", In = ParameterLocation.Path }; - public static OpenApiParameterReference OpenApiParameterReference = new(ReferencedParameter, "example1"); - public static OpenApiParameter ReferencedParameter = new() + private static OpenApiParameterReference OpenApiParameterReference => new("example1"); + private static OpenApiParameter ReferencedParameter => new() { Name = "name1", In = ParameterLocation.Path }; - public static OpenApiParameter AdvancedPathParameterWithSchema = new() + private static OpenApiParameter AdvancedPathParameterWithSchema => new() { Name = "name1", In = ParameterLocation.Path, @@ -40,14 +41,14 @@ public class OpenApiParameterTests Deprecated = false, Style = ParameterStyle.Simple, Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Title = "title2", Description = "description2", - OneOf = new List + OneOf = new List { - new() { Type = JsonSchemaType.Number, Format = "double" }, - new() { Type = JsonSchemaType.String } + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "double" }, + new OpenApiSchema() { Type = JsonSchemaType.String } } }, Examples = @@ -60,17 +61,17 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter ParameterWithFormStyleAndExplodeFalse = new() + private static OpenApiParameter ParameterWithFormStyleAndExplodeFalse => new() { Name = "name1", In = ParameterLocation.Query, Description = "description1", Style = ParameterStyle.Form, Explode = false, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Enum = { @@ -81,17 +82,17 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter ParameterWithFormStyleAndExplodeTrue = new() + private static OpenApiParameter ParameterWithFormStyleAndExplodeTrue => new() { Name = "name1", In = ParameterLocation.Query, Description = "description1", Style = ParameterStyle.Form, Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Enum = [ @@ -102,11 +103,11 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter QueryParameterWithMissingStyle = new OpenApiParameter + private static OpenApiParameter QueryParameterWithMissingStyle => new OpenApiParameter { Name = "id", In = ParameterLocation.Query, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, AdditionalProperties = new OpenApiSchema @@ -116,7 +117,7 @@ public class OpenApiParameterTests } }; - public static OpenApiParameter AdvancedHeaderParameterWithSchemaReference = new OpenApiParameter + private static OpenApiParameter AdvancedHeaderParameterWithSchemaTypeObject => new() { Name = "name1", In = ParameterLocation.Header, @@ -126,36 +127,7 @@ public class OpenApiParameterTests Style = ParameterStyle.Simple, Explode = true, - Schema = new() - { - Reference = new() - { - Type = ReferenceType.Schema, - Id = "schemaObject1" - }, - UnresolvedReference = true - }, - Examples = - { - ["test"] = new OpenApiExample() - { - Summary = "summary3", - Description = "description3" - } - } - }; - - public static OpenApiParameter AdvancedHeaderParameterWithSchemaTypeObject = new() - { - Name = "name1", - In = ParameterLocation.Header, - Description = "description1", - Required = true, - Deprecated = false, - - Style = ParameterStyle.Simple, - Explode = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object }, diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs index f391ef4d8..863ce5145 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiRequestBodyTests.cs @@ -15,7 +15,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiRequestBodyTests { - public static OpenApiRequestBody AdvancedRequestBody = new() + private static OpenApiRequestBody AdvancedRequestBody => new() { Description = "description", Required = true, @@ -23,7 +23,7 @@ public class OpenApiRequestBodyTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -31,8 +31,8 @@ public class OpenApiRequestBodyTests } }; - public static OpenApiRequestBodyReference OpenApiRequestBodyReference = new(ReferencedRequestBody, "example1"); - public static OpenApiRequestBody ReferencedRequestBody = new() + private static OpenApiRequestBodyReference OpenApiRequestBodyReference => new("example1"); + private static OpenApiRequestBody ReferencedRequestBody => new() { Description = "description", Required = true, @@ -40,7 +40,7 @@ public class OpenApiRequestBodyTests { ["application/json"] = new() { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs index f0991a1cb..7d077b540 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiResponseTests.cs @@ -20,16 +20,16 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiResponseTests { - public static OpenApiResponse BasicResponse = new OpenApiResponse(); + private static OpenApiResponse BasicResponse => new OpenApiResponse(); - public static OpenApiResponse AdvancedV2Response = new OpenApiResponse + private static OpenApiResponse AdvancedV2Response => new OpenApiResponse { Description = "A complex object array response", Content = { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -46,7 +46,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -54,21 +54,21 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } }, } }; - public static OpenApiResponse AdvancedV3Response = new OpenApiResponse + private static OpenApiResponse AdvancedV3Response => new OpenApiResponse { Description = "A complex object array response", Content = { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -85,7 +85,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -93,7 +93,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -101,15 +101,15 @@ public class OpenApiResponseTests } }; - public static OpenApiResponseReference V2OpenApiResponseReference = new OpenApiResponseReference(ReferencedV2Response, "example1"); - public static OpenApiResponse ReferencedV2Response = new OpenApiResponse + private static OpenApiResponseReference V2OpenApiResponseReference => new OpenApiResponseReference("example1"); + private static OpenApiResponse ReferencedV2Response => new OpenApiResponse { Description = "A complex object array response", Content = { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -121,7 +121,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -129,23 +129,23 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } }, } }; - public static OpenApiResponseReference V3OpenApiResponseReference = new OpenApiResponseReference(ReferencedV3Response, "example1"); + private static OpenApiResponseReference V3OpenApiResponseReference => new OpenApiResponseReference("example1"); - public static OpenApiResponse ReferencedV3Response = new OpenApiResponse + private static OpenApiResponse ReferencedV3Response => new OpenApiResponse { Description = "A complex object array response", Content = { ["text/plain"] = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Array, Items = new OpenApiSchemaReference("customType", null) @@ -157,7 +157,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Limit"] = new OpenApiHeader { Description = "The number of allowed requests in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -165,7 +165,7 @@ public class OpenApiResponseTests ["X-Rate-Limit-Reset"] = new OpenApiHeader { Description = "The number of seconds left in the current period", - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -173,13 +173,6 @@ public class OpenApiResponseTests } }; - private readonly ITestOutputHelper _output; - - public OpenApiResponseTests(ITestOutputHelper output) - { - _output = output; - } - [Theory] [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json)] [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json)] diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt index b431f1607..aac504993 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt @@ -5,8 +5,8 @@ "minimum": 10, "exclusiveMinimum": true, "type": "integer", - "default": 15, "nullable": true, + "default": 15, "externalDocs": { "url": "http://example.com/externalDocs" } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt index d71a5f0a8..3ed4ce5c8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"title":"title1","multipleOf":3,"maximum":42,"minimum":10,"exclusiveMinimum":true,"type":"integer","default":15,"nullable":true,"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file +{"title":"title1","multipleOf":3,"maximum":42,"minimum":10,"exclusiveMinimum":true,"type":"integer","nullable":true,"default":15,"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=False.verified.txt index b431f1607..aac504993 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=False.verified.txt @@ -5,8 +5,8 @@ "minimum": 10, "exclusiveMinimum": true, "type": "integer", - "default": 15, "nullable": true, + "default": 15, "externalDocs": { "url": "http://example.com/externalDocs" } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=True.verified.txt index d71a5f0a8..3ed4ce5c8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeReferencedSchemaAsV3WithoutReferenceJsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"title":"title1","multipleOf":3,"maximum":42,"minimum":10,"exclusiveMinimum":true,"type":"integer","default":15,"nullable":true,"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file +{"title":"title1","multipleOf":3,"maximum":42,"minimum":10,"exclusiveMinimum":true,"type":"integer","nullable":true,"default":15,"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt index e9543ede7..e30457226 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt @@ -1,4 +1,6 @@ { + "type": "object", + "x-nullable": true, "title": "title1", "required": [ "property1" diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt index 9ea88dee8..d5d9596f0 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.SerializeSchemaWRequiredPropertiesAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"title":"title1","required":["property1"],"properties":{"property1":{"required":["property3"],"properties":{"property2":{"type":"integer"},"property3":{"type":"string","maxLength":15}}},"property4":{"properties":{"property5":{"properties":{"property6":{"type":"boolean"}}},"property7":{"type":"string","minLength":2}},"readOnly":true}},"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file +{"type":"object","x-nullable":true,"title":"title1","required":["property1"],"properties":{"property1":{"required":["property3"],"properties":{"property2":{"type":"integer"},"property3":{"type":"string","maxLength":15}}},"property4":{"properties":{"property5":{"properties":{"property6":{"type":"boolean"}}},"property7":{"type":"string","minLength":2}},"readOnly":true}},"externalDocs":{"url":"http://example.com/externalDocs"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index 5edd1c0d0..76d6c00fa 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -12,6 +12,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Writers; using VerifyXunit; @@ -32,9 +33,8 @@ public class OpenApiSchemaTests ExclusiveMinimum = true, Minimum = 10, Default = 15, - Type = JsonSchemaType.Integer, + Type = JsonSchemaType.Integer | JsonSchemaType.Null, - Nullable = true, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -45,38 +45,38 @@ public class OpenApiSchemaTests public static readonly OpenApiSchema AdvancedSchemaObject = new() { Title = "title1", - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 } }, }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property5"] = new() + ["property5"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property6"] = new() + ["property6"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property7"] = new() + ["property7"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 @@ -84,7 +84,7 @@ public class OpenApiSchemaTests }, }, }, - Nullable = true, + Type = JsonSchemaType.Object | JsonSchemaType.Null, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -94,49 +94,49 @@ public class OpenApiSchemaTests public static readonly OpenApiSchema AdvancedSchemaWithAllOf = new() { Title = "title1", - AllOf = new List + AllOf = new List { - new() + new OpenApiSchema() { Title = "title2", - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15 } }, }, - new() + new OpenApiSchema() { Title = "title3", - Properties = new Dictionary + Properties = new Dictionary { - ["property3"] = new() + ["property3"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property4"] = new() + ["property4"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property5"] = new() + ["property5"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 } }, - Nullable = true + Type = JsonSchemaType.Object | JsonSchemaType.Null, }, }, - Nullable = true, + Type = JsonSchemaType.Object | JsonSchemaType.Null, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -151,9 +151,8 @@ public class OpenApiSchemaTests ExclusiveMinimum = true, Minimum = 10, Default = 15, - Type = JsonSchemaType.Integer, + Type = JsonSchemaType.Integer | JsonSchemaType.Null, - Nullable = true, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -164,18 +163,18 @@ public class OpenApiSchemaTests { Title = "title1", Required = new HashSet { "property1" }, - Properties = new Dictionary + Properties = new Dictionary { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Required = new HashSet { "property3" }, - Properties = new Dictionary + Properties = new Dictionary { - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Integer }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, MaxLength = 15, @@ -184,21 +183,21 @@ public class OpenApiSchemaTests }, ReadOnly = true, }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property5"] = new() + ["property5"] = new OpenApiSchema() { - Properties = new Dictionary + Properties = new Dictionary { - ["property6"] = new() + ["property6"] = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property7"] = new() + ["property7"] = new OpenApiSchema() { Type = JsonSchemaType.String, MinLength = 2 @@ -207,7 +206,7 @@ public class OpenApiSchemaTests ReadOnly = true, }, }, - Nullable = true, + Type = JsonSchemaType.Object | JsonSchemaType.Null, ExternalDocs = new() { Url = new("http://example.com/externalDocs") @@ -242,8 +241,8 @@ public async Task SerializeAdvancedSchemaNumberAsV3JsonWorks() "minimum": 10, "exclusiveMinimum": true, "type": "integer", - "default": 15, "nullable": true, + "default": 15, "externalDocs": { "url": "http://example.com/externalDocs" } @@ -254,9 +253,7 @@ public async Task SerializeAdvancedSchemaNumberAsV3JsonWorks() var actual = await AdvancedSchemaNumber.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -267,6 +264,8 @@ public async Task SerializeAdvancedSchemaObjectAsV3JsonWorks() """ { "title": "title1", + "type": "object", + "nullable": true, "properties": { "property1": { "properties": { @@ -295,7 +294,6 @@ public async Task SerializeAdvancedSchemaObjectAsV3JsonWorks() } } }, - "nullable": true, "externalDocs": { "url": "http://example.com/externalDocs" } @@ -306,9 +304,7 @@ public async Task SerializeAdvancedSchemaObjectAsV3JsonWorks() var actual = await AdvancedSchemaObject.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -319,6 +315,8 @@ public async Task SerializeAdvancedSchemaWithAllOfAsV3JsonWorks() """ { "title": "title1", + "type": "object", + "nullable": true, "allOf": [ { "title": "title2", @@ -334,6 +332,8 @@ public async Task SerializeAdvancedSchemaWithAllOfAsV3JsonWorks() }, { "title": "title3", + "type": "object", + "nullable": true, "properties": { "property3": { "properties": { @@ -346,11 +346,9 @@ public async Task SerializeAdvancedSchemaWithAllOfAsV3JsonWorks() "minLength": 2, "type": "string" } - }, - "nullable": true + } } ], - "nullable": true, "externalDocs": { "url": "http://example.com/externalDocs" } @@ -361,9 +359,7 @@ public async Task SerializeAdvancedSchemaWithAllOfAsV3JsonWorks() var actual = await AdvancedSchemaWithAllOf.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonObject.DeepEquals(JsonObject.Parse(expected), JsonObject.Parse(actual))); } [Theory] @@ -423,14 +419,14 @@ public async Task SerializeAsV2ShouldSetFormatPropertyInParentSchemaIfPresentInC // Arrange var schema = new OpenApiSchema { - OneOf = new List + OneOf = new List { - new() + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "decimal" }, - new() { Type = JsonSchemaType.String }, + new OpenApiSchema() { Type = JsonSchemaType.String }, } }; @@ -470,14 +466,12 @@ public void OpenApiSchemaCopyConstructorSucceeds() Format = "date" }; - var actualSchema = new OpenApiSchema(baseSchema) - { - Nullable = true - }; + var actualSchema = baseSchema.CreateShallowCopy() as OpenApiSchema; + actualSchema.Type |= JsonSchemaType.Null; - Assert.Equal(JsonSchemaType.String, actualSchema.Type); + Assert.Equal(JsonSchemaType.String, actualSchema.Type & JsonSchemaType.String); + Assert.Equal(JsonSchemaType.Null, actualSchema.Type & JsonSchemaType.Null); Assert.Equal("date", actualSchema.Format); - Assert.True(actualSchema.Nullable); } [Fact] @@ -492,7 +486,7 @@ public void OpenApiSchemaCopyConstructorWithAnnotationsSucceeds() } }; - var actualSchema = new OpenApiSchema(baseSchema); + var actualSchema = baseSchema.CreateShallowCopy(); Assert.Equal(baseSchema.Annotations["key1"], actualSchema.Annotations["key1"]); @@ -530,7 +524,7 @@ public void CloningSchemaExamplesWorks(JsonNode example) }; // Act && Assert - var schemaCopy = new OpenApiSchema(schema); + var schemaCopy = schema.CreateShallowCopy(); // Act && Assert schema.Example.Should().BeEquivalentTo(schemaCopy.Example, options => options @@ -551,7 +545,7 @@ public void CloningSchemaExtensionsWorks() }; // Act && Assert - var schemaCopy = new OpenApiSchema(schema); + var schemaCopy = schema.CreateShallowCopy() as OpenApiSchema; Assert.Single(schemaCopy.Extensions); // Act && Assert @@ -630,11 +624,41 @@ public async Task SerializeSchemaWithUnrecognizedPropertiesWorks() Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral()); } + [Fact] + public async Task WriteAsItemsPropertiesDoesNotWriteNull() + { + // Arrange + var schema = new OpenApiSchema + { + Type = JsonSchemaType.Number | JsonSchemaType.Null + }; + + var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); + var writer = new OpenApiJsonWriter(outputStringWriter, new() { Terse = false }); + writer.WriteStartObject(); + + // Act + schema.WriteAsItemsProperties(writer); + writer.WriteEndObject(); + await writer.FlushAsync(); + + // Assert + var actual = outputStringWriter.GetStringBuilder().ToString(); + var expected = + """ + { + "type": "number" + } + """; + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); + } + + internal class SchemaVisitor : OpenApiVisitorBase { public List Titles = new(); - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { Titles.Add(schema.Title); } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs index af0343f57..cfbe0ae50 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs @@ -13,6 +13,8 @@ using VerifyXunit; using Microsoft.OpenApi.Models.References; using Xunit; +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Tests.Models { @@ -25,7 +27,7 @@ public class OpenApiSecurityRequirementTests new() { [ - new OpenApiSecuritySchemeReference("scheme1", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme1", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List { "scope1", @@ -33,22 +35,56 @@ public class OpenApiSecurityRequirementTests "scope3", }, [ - new OpenApiSecuritySchemeReference("scheme2", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme2", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List { "scope4", "scope5", }, [ - new OpenApiSecuritySchemeReference("scheme3", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme3", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List() }; + public static OpenApiDocument SecurityRequirementWithReferencedSecurityScheme_supportingDocument + { + get + { + var document = new OpenApiDocument() + { + Components = new() + { + SecuritySchemes = new Dictionary + { + ["scheme1"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.ApiKey, + Name = "apiKeyName1", + In = ParameterLocation.Header, + }, + ["scheme2"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OpenIdConnect, + OpenIdConnectUrl = new("http://example.com"), + }, + ["scheme3"] = new OpenApiSecurityScheme + { + Type = SecuritySchemeType.Http, + Scheme = "bearer", + BearerFormat = "JWT", + }, + } + } + }; + document.RegisterComponents(); + return document; + } + } public static OpenApiSecurityRequirement SecurityRequirementWithUnreferencedSecurityScheme = new() { [ - new OpenApiSecuritySchemeReference("scheme1", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme1", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List { "scope1", @@ -56,18 +92,14 @@ public class OpenApiSecurityRequirementTests "scope3", }, [ - new() - { - // This security scheme is unreferenced, so this key value pair cannot be serialized. - Name = "brokenUnreferencedScheme" - } + new OpenApiSecuritySchemeReference("brokenUnreferencedScheme", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List { "scope4", "scope5", }, [ - new OpenApiSecuritySchemeReference("scheme3", hostDocument: null) + new OpenApiSecuritySchemeReference("scheme3", SecurityRequirementWithReferencedSecurityScheme_supportingDocument) ] = new List() }; @@ -127,9 +159,7 @@ public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV3Js var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -156,9 +186,7 @@ public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV2Js var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -181,9 +209,7 @@ public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV3 var actual = await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -207,9 +233,7 @@ public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV2 await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); // Assert - actual = actual.MakeLineBreaksEnvironmentNeutral(); - expected = expected.MakeLineBreaksEnvironmentNeutral(); - Assert.Equal(expected, actual); + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); } [Fact] @@ -223,22 +247,12 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality() Type = SecuritySchemeType.ApiKey, Name = "apiKeyName1", In = ParameterLocation.Header, - Reference = new() - { - Id = "securityScheme1", - Type = ReferenceType.SecurityScheme - } }; var securityScheme2 = new OpenApiSecurityScheme { Type = SecuritySchemeType.OpenIdConnect, OpenIdConnectUrl = new("http://example.com"), - Reference = new() - { - Id = "securityScheme2", - Type = ReferenceType.SecurityScheme - } }; var securityScheme1Duplicate = new OpenApiSecurityScheme @@ -246,11 +260,6 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality() Type = SecuritySchemeType.ApiKey, Name = "apiKeyName1", In = ParameterLocation.Header, - Reference = new() - { - Id = "securityScheme1", - Type = ReferenceType.SecurityScheme - } }; var securityScheme1WithDifferentProperties = new OpenApiSecurityScheme @@ -258,21 +267,16 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality() Type = SecuritySchemeType.ApiKey, Name = "apiKeyName2", In = ParameterLocation.Query, - Reference = new() - { - Id = "securityScheme1", - Type = ReferenceType.SecurityScheme - } }; // Act - securityRequirement.Add(securityScheme1, new List()); - securityRequirement.Add(securityScheme2, new List { "scope1", "scope2" }); + securityRequirement.Add(new OpenApiSecuritySchemeReference("securityScheme1"), new List()); + securityRequirement.Add(new OpenApiSecuritySchemeReference("securityScheme2"), new List { "scope1", "scope2" }); var addSecurityScheme1Duplicate = () => - securityRequirement.Add(securityScheme1Duplicate, new List()); + securityRequirement.Add(new OpenApiSecuritySchemeReference("securityScheme1"), new List()); var addSecurityScheme1WithDifferentProperties = () => - securityRequirement.Add(securityScheme1WithDifferentProperties, new List()); + securityRequirement.Add(new OpenApiSecuritySchemeReference("securityScheme1"), new List()); // Assert // Only the first two should be added successfully since the latter two are duplicates of securityScheme1. @@ -287,8 +291,8 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality() { // This should work with any security scheme object // as long as Reference.Id os securityScheme1 - [securityScheme1WithDifferentProperties] = new List(), - [securityScheme2] = new List { "scope1", "scope2" }, + [new OpenApiSecuritySchemeReference("securityScheme1", null)] = new List(), + [new OpenApiSecuritySchemeReference("securityScheme2", null)] = new List { "scope1", "scope2" }, }); } } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs index 9c59ca4bd..12db6c1e8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs @@ -17,7 +17,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiSecuritySchemeTests { - public static OpenApiSecurityScheme ApiKeySecurityScheme = new() + private static OpenApiSecurityScheme ApiKeySecurityScheme => new() { Description = "description1", Name = "parameterName", @@ -25,14 +25,14 @@ public class OpenApiSecuritySchemeTests In = ParameterLocation.Query, }; - public static OpenApiSecurityScheme HttpBasicSecurityScheme = new() + private static OpenApiSecurityScheme HttpBasicSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.Http, Scheme = OpenApiConstants.Basic }; - public static OpenApiSecurityScheme HttpBearerSecurityScheme = new() + private static OpenApiSecurityScheme HttpBearerSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.Http, @@ -40,7 +40,7 @@ public class OpenApiSecuritySchemeTests BearerFormat = OpenApiConstants.Jwt }; - public static OpenApiSecurityScheme OAuth2SingleFlowSecurityScheme = new() + private static OpenApiSecurityScheme OAuth2SingleFlowSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.OAuth2, @@ -58,7 +58,7 @@ public class OpenApiSecuritySchemeTests } }; - public static OpenApiSecurityScheme OAuth2MultipleFlowSecurityScheme = new() + private static OpenApiSecurityScheme OAuth2MultipleFlowSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.OAuth2, @@ -96,7 +96,7 @@ public class OpenApiSecuritySchemeTests } }; - public static OpenApiSecurityScheme OpenIdConnectSecurityScheme = new() + private static OpenApiSecurityScheme OpenIdConnectSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.OpenIdConnect, @@ -104,8 +104,8 @@ public class OpenApiSecuritySchemeTests OpenIdConnectUrl = new("https://example.com/openIdConnect") }; - public static OpenApiSecuritySchemeReference OpenApiSecuritySchemeReference = new(target: ReferencedSecurityScheme, referenceId: "sampleSecurityScheme"); - public static OpenApiSecurityScheme ReferencedSecurityScheme = new() + private static OpenApiSecuritySchemeReference OpenApiSecuritySchemeReference => new("sampleSecurityScheme"); + private static OpenApiSecurityScheme ReferencedSecurityScheme => new() { Description = "description1", Type = SecuritySchemeType.OpenIdConnect, diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt deleted file mode 100644 index 2afa516e0..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "pet", - "description": "Pets operations", - "externalDocs": { - "description": "Find more info here", - "url": "https://example.com" - }, - "x-tag-extension": null -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index f0a901938..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"name":"pet","description":"Pets operations","externalDocs":{"description":"Find more info here","url":"https://example.com"},"x-tag-extension":null} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt deleted file mode 100644 index 2afa516e0..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "pet", - "description": "Pets operations", - "externalDocs": { - "description": "Find more info here", - "url": "https://example.com" - }, - "x-tag-extension": null -} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt deleted file mode 100644 index f0a901938..000000000 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt +++ /dev/null @@ -1 +0,0 @@ -{"name":"pet","description":"Pets operations","externalDocs":{"description":"Find more info here","url":"https://example.com"},"x-tag-extension":null} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs index 508779adf..73ac0d0b7 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using VerifyXunit; @@ -30,7 +31,7 @@ public class OpenApiTagTests } }; - public static OpenApiTag ReferencedTag = new OpenApiTagReference("pet", null); + public static IOpenApiTag ReferencedTag = new OpenApiTagReference("pet"); [Theory] [InlineData(true)] diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs index 4f8e24f6e..ef9bea785 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs @@ -109,13 +109,15 @@ public void RequestBodyReferenceResolutionWorks() // Assert var localContent = _localRequestBodyReference.Content.Values.FirstOrDefault(); Assert.NotNull(localContent); - Assert.Equal("UserSchema", localContent.Schema.Reference.Id); + var localContentSchema = Assert.IsType(localContent.Schema); + Assert.Equal("UserSchema", localContentSchema.Reference.Id); Assert.Equal("User request body", _localRequestBodyReference.Description); Assert.Equal("application/json", _localRequestBodyReference.Content.First().Key); var externalContent = _externalRequestBodyReference.Content.Values.FirstOrDefault(); Assert.NotNull(externalContent); - Assert.Equal("UserSchema", externalContent.Schema.Reference.Id); + var externalContentSchema = Assert.IsType(externalContent.Schema); + Assert.Equal("UserSchema", externalContentSchema.Reference.Id); Assert.Equal("External Reference: User request body", _externalRequestBodyReference.Description); Assert.Equal("User creation request body", _openApiDoc_2.Components.RequestBodies.First().Value.Description); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs index 196759540..785ea5e55 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs @@ -92,12 +92,14 @@ public void ResponseReferenceResolutionWorks() // Assert var localContent = _localResponseReference.Content.FirstOrDefault(); Assert.Equal("text/plain", localContent.Key); - Assert.Equal("Pong", localContent.Value.Schema.Reference.Id); + var localContentSchema = Assert.IsType(localContent.Value.Schema); + Assert.Equal("Pong", localContentSchema.Reference.Id); Assert.Equal("OK response", _localResponseReference.Description); var externalContent = _externalResponseReference.Content.FirstOrDefault(); Assert.Equal("text/plain", externalContent.Key); - Assert.Equal("Pong", externalContent.Value.Schema.Reference.Id); + var externalContentSchema = Assert.IsType(externalContent.Value.Schema); + Assert.Equal("Pong", externalContentSchema.Reference.Id); Assert.Equal("External reference: OK response", _externalResponseReference.Description); Assert.Equal("OK", _openApiDoc_2.Components.Responses.First().Value.Description); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..a73e7078d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "mySecurityScheme" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..5c70082e7 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"mySecurityScheme"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV31JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..a73e7078d --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=False.verified.txt @@ -0,0 +1,3 @@ +{ + "$ref": "mySecurityScheme" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=False_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt new file mode 100644 index 000000000..5c70082e7 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=False.verified.txt @@ -0,0 +1 @@ +{"$ref":"mySecurityScheme"} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt similarity index 100% rename from test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt rename to test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.SerializeSecuritySchemeReferenceAsV3JsonWorks_produceTerseOutput=True_inlineLocalReferences=True.verified.txt diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs index d13d63c9a..56b7e6d07 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs @@ -57,37 +57,41 @@ public void SecuritySchemeResolutionWorks() } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeSecuritySchemeReferenceAsV3JsonWorks(bool produceTerseOutput) + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(true, true)] + [InlineData(false, true)] + public async Task SerializeSecuritySchemeReferenceAsV3JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _openApiSecuritySchemeReference.SerializeAsV3(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeSecuritySchemeReferenceAsV31JsonWorks(bool produceTerseOutput) + [InlineData(true, false)] + [InlineData(false, false)] + [InlineData(true, true)] + [InlineData(false, true)] + public async Task SerializeSecuritySchemeReferenceAsV31JsonWorks(bool produceTerseOutput, bool inlineLocalReferences) { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = true }); + var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput, InlineLocalReferences = inlineLocalReferences }); // Act _openApiSecuritySchemeReference.SerializeAsV31(writer); await writer.FlushAsync(); // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); + await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput, inlineLocalReferences); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs index 9d409c24b..250f8ee53 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs @@ -74,7 +74,6 @@ public void TagReferenceResolutionWorks() // Assert Assert.Equal("user", _openApiTagReference.Name); Assert.Equal("Operations about users.", _openApiTagReference.Description); - Assert.Throws(() => _openApiTagReference.Description = "New Description"); } [Theory] diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index e5c9f7bb1..8b69cb508 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -224,17 +224,13 @@ namespace Microsoft.OpenApi.Interfaces } public interface IOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { - Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - bool UnresolvedReference { get; set; } + bool UnresolvedReference { get; } + Microsoft.OpenApi.Models.OpenApiReference Reference { get; init; } } - public interface IOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - where out T : Microsoft.OpenApi.Interfaces.IOpenApiReferenceable - { - T Target { get; } - } - public interface IOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public interface IOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable where out T : Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, V { + T Target { get; } V CopyReferenceAsTargetElementWithOverrides(V source); } public interface IOpenApiReferenceable : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { } @@ -244,6 +240,10 @@ namespace Microsoft.OpenApi.Interfaces void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer); void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer); } + public interface IShallowCopyable + { + T CreateShallowCopy(); + } public interface IStreamLoader { System.Threading.Tasks.Task LoadAsync(System.Uri uri); @@ -337,7 +337,7 @@ namespace Microsoft.OpenApi.MicrosoftExtensions } namespace Microsoft.OpenApi.Models.Interfaces { - public interface IOpenApiCallback : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public interface IOpenApiCallback : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable { System.Collections.Generic.Dictionary PathItems { get; } } @@ -345,12 +345,12 @@ namespace Microsoft.OpenApi.Models.Interfaces { string Description { get; set; } } - public interface IOpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + public interface IOpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { string ExternalValue { get; } System.Text.Json.Nodes.JsonNode Value { get; } } - public interface IOpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + public interface IOpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement { bool AllowEmptyValue { get; } bool AllowReserved { get; } @@ -360,10 +360,10 @@ namespace Microsoft.OpenApi.Models.Interfaces System.Collections.Generic.IDictionary Examples { get; } bool Explode { get; } bool Required { get; } - Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } Microsoft.OpenApi.Models.ParameterStyle? Style { get; } } - public interface IOpenApiLink : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + public interface IOpenApiLink : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement { string OperationId { get; } string OperationRef { get; } @@ -371,7 +371,7 @@ namespace Microsoft.OpenApi.Models.Interfaces Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; } Microsoft.OpenApi.Models.OpenApiServer Server { get; } } - public interface IOpenApiParameter : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + public interface IOpenApiParameter : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement { bool AllowEmptyValue { get; } bool AllowReserved { get; } @@ -383,32 +383,104 @@ namespace Microsoft.OpenApi.Models.Interfaces Microsoft.OpenApi.Models.ParameterLocation? In { get; } string Name { get; } bool Required { get; } - Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } Microsoft.OpenApi.Models.ParameterStyle? Style { get; } } - public interface IOpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + public interface IOpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { System.Collections.Generic.IDictionary Operations { get; } System.Collections.Generic.IList Parameters { get; } System.Collections.Generic.IList Servers { get; } } - public interface IOpenApiRequestBody : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + public interface IOpenApiReadOnlyDescribedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement + { + string Description { get; } + } + public interface IOpenApiRequestBody : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement { System.Collections.Generic.IDictionary Content { get; } bool Required { get; } Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter ConvertToBodyParameter(Microsoft.OpenApi.Writers.IOpenApiWriter writer); System.Collections.Generic.IEnumerable ConvertToFormDataParameters(Microsoft.OpenApi.Writers.IOpenApiWriter writer); } - public interface IOpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + public interface IOpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement { System.Collections.Generic.IDictionary Content { get; } System.Collections.Generic.IDictionary Headers { get; } System.Collections.Generic.IDictionary Links { get; } } + public interface IOpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; } + bool AdditionalPropertiesAllowed { get; } + System.Collections.Generic.IList AllOf { get; } + System.Collections.Generic.IDictionary Annotations { get; } + System.Collections.Generic.IList AnyOf { get; } + string Comment { get; } + string Const { get; } + System.Text.Json.Nodes.JsonNode Default { get; } + System.Collections.Generic.IDictionary Definitions { get; } + bool Deprecated { get; } + Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; } + string DynamicAnchor { get; } + string DynamicRef { get; } + System.Collections.Generic.IList Enum { get; } + System.Text.Json.Nodes.JsonNode Example { get; } + System.Collections.Generic.IList Examples { get; } + bool? ExclusiveMaximum { get; } + bool? ExclusiveMinimum { get; } + Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + string Format { get; } + string Id { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; } + int? MaxItems { get; } + int? MaxLength { get; } + int? MaxProperties { get; } + decimal? Maximum { get; } + int? MinItems { get; } + int? MinLength { get; } + int? MinProperties { get; } + decimal? Minimum { get; } + decimal? MultipleOf { get; } + Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; } + System.Collections.Generic.IList OneOf { get; } + string Pattern { get; } + System.Collections.Generic.IDictionary PatternProperties { get; } + System.Collections.Generic.IDictionary Properties { get; } + bool ReadOnly { get; } + System.Collections.Generic.ISet Required { get; } + string Schema { get; } + string Title { get; } + Microsoft.OpenApi.Models.JsonSchemaType? Type { get; } + bool UnEvaluatedProperties { get; } + bool UnevaluatedProperties { get; } + bool? UniqueItems { get; } + System.Collections.Generic.IDictionary UnrecognizedKeywords { get; } + decimal? V31ExclusiveMaximum { get; } + decimal? V31ExclusiveMinimum { get; } + System.Collections.Generic.IDictionary Vocabulary { get; } + bool WriteOnly { get; } + Microsoft.OpenApi.Models.OpenApiXml Xml { get; } + } + public interface IOpenApiSecurityScheme : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + string BearerFormat { get; } + Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; } + Microsoft.OpenApi.Models.ParameterLocation? In { get; } + string Name { get; } + System.Uri OpenIdConnectUrl { get; } + string Scheme { get; } + Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; } + } public interface IOpenApiSummarizedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement { string Summary { get; set; } } + public interface IOpenApiTag : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiReadOnlyDescribedElement + { + Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + string Name { get; } + } } namespace Microsoft.OpenApi.Models { @@ -423,13 +495,13 @@ namespace Microsoft.OpenApi.Models Object = 32, Array = 64, } - public class OpenApiCallback : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback + public class OpenApiCallback : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback { public OpenApiCallback() { } - public OpenApiCallback(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback callback) { } public System.Collections.Generic.IDictionary Extensions { get; set; } public System.Collections.Generic.Dictionary PathItems { get; set; } public void AddPathItem(Microsoft.OpenApi.Expressions.RuntimeExpression expression, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -447,8 +519,8 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary? PathItems { get; set; } public System.Collections.Generic.IDictionary? RequestBodies { get; set; } public System.Collections.Generic.IDictionary? Responses { get; set; } - public System.Collections.Generic.IDictionary? Schemas { get; set; } - public System.Collections.Generic.IDictionary? SecuritySchemes { get; set; } + public System.Collections.Generic.IDictionary? Schemas { get; set; } + public System.Collections.Generic.IDictionary? SecuritySchemes { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -652,6 +724,7 @@ namespace Microsoft.OpenApi.Models public Microsoft.OpenApi.Services.OpenApiWorkspace? Workspace { get; set; } public bool AddComponent(string id, T componentToRegister) { } public System.Threading.Tasks.Task GetHashCodeAsync(System.Threading.CancellationToken cancellationToken = default) { } + public void RegisterComponents() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -684,15 +757,15 @@ namespace Microsoft.OpenApi.Models public string Pointer { get; set; } public override string ToString() { } } - public class OpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + public class OpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { public OpenApiExample() { } - public OpenApiExample(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample example) { } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } public string ExternalValue { get; set; } public string Summary { get; set; } public System.Text.Json.Nodes.JsonNode Value { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiExample CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -718,10 +791,9 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader + public class OpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader { public OpenApiHeader() { } - public OpenApiHeader(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader header) { } public bool AllowEmptyValue { get; set; } public bool AllowReserved { get; set; } public System.Collections.Generic.IDictionary Content { get; set; } @@ -732,8 +804,9 @@ namespace Microsoft.OpenApi.Models public bool Explode { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } public bool Required { get; set; } - public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; set; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -766,10 +839,9 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiLink : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiLink + public class OpenApiLink : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiLink { public OpenApiLink() { } - public OpenApiLink(Microsoft.OpenApi.Models.Interfaces.IOpenApiLink link) { } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } public string OperationId { get; set; } @@ -777,6 +849,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary Parameters { get; set; } public Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; set; } public Microsoft.OpenApi.Models.OpenApiServer Server { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiLink CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -789,7 +862,7 @@ namespace Microsoft.OpenApi.Models public System.Text.Json.Nodes.JsonNode? Example { get; set; } public System.Collections.Generic.IDictionary? Examples { get; set; } public System.Collections.Generic.IDictionary? Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema? Schema { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema? Schema { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -824,7 +897,7 @@ namespace Microsoft.OpenApi.Models { public const bool DeprecatedDefault = false; public OpenApiOperation() { } - public OpenApiOperation(Microsoft.OpenApi.Models.OpenApiOperation? operation) { } + public OpenApiOperation(Microsoft.OpenApi.Models.OpenApiOperation operation) { } public System.Collections.Generic.IDictionary? Annotations { get; set; } public System.Collections.Generic.IDictionary? Callbacks { get; set; } public bool Deprecated { get; set; } @@ -843,10 +916,9 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiParameter : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter + public class OpenApiParameter : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter { public OpenApiParameter() { } - public OpenApiParameter(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter parameter) { } public bool AllowEmptyValue { get; set; } public bool AllowReserved { get; set; } public System.Collections.Generic.IDictionary Content { get; set; } @@ -859,16 +931,16 @@ namespace Microsoft.OpenApi.Models public Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } public string Name { get; set; } public bool Required { get; set; } - public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; set; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + public class OpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { public OpenApiPathItem() { } - public OpenApiPathItem(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } public System.Collections.Generic.IDictionary Operations { get; set; } @@ -876,6 +948,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IList Servers { get; set; } public string Summary { get; set; } public void AddOperation(Microsoft.OpenApi.Models.OperationType operationType, Microsoft.OpenApi.Models.OpenApiOperation operation) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -885,48 +958,48 @@ namespace Microsoft.OpenApi.Models public OpenApiPaths() { } public OpenApiPaths(Microsoft.OpenApi.Models.OpenApiPaths paths) { } } - public class OpenApiReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { - public bool IsFragment; public OpenApiReference() { } public OpenApiReference(Microsoft.OpenApi.Models.OpenApiReference reference) { } public string Description { get; set; } - public string ExternalResource { get; set; } - public Microsoft.OpenApi.Models.OpenApiDocument HostDocument { get; set; } - public string Id { get; set; } public bool IsExternal { get; } public bool IsLocal { get; } public string ReferenceV2 { get; } public string ReferenceV3 { get; } public string Summary { get; set; } - public Microsoft.OpenApi.Models.ReferenceType? Type { get; set; } + public string ExternalResource { get; init; } + public Microsoft.OpenApi.Models.OpenApiDocument HostDocument { get; init; } + public string Id { get; init; } + public bool IsFragment { get; init; } + public Microsoft.OpenApi.Models.ReferenceType? Type { get; init; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiRequestBody : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody + public class OpenApiRequestBody : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody { public OpenApiRequestBody() { } - public OpenApiRequestBody(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } public System.Collections.Generic.IDictionary Content { get; set; } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } public bool Required { get; set; } public Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter ConvertToBodyParameter(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public System.Collections.Generic.IEnumerable ConvertToFormDataParameters(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse + public class OpenApiResponse : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse { public OpenApiResponse() { } - public OpenApiResponse(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } public System.Collections.Generic.IDictionary Content { get; set; } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } public System.Collections.Generic.IDictionary Headers { get; set; } public System.Collections.Generic.IDictionary Links { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse CreateShallowCopy() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -936,94 +1009,89 @@ namespace Microsoft.OpenApi.Models public OpenApiResponses() { } public OpenApiResponses(Microsoft.OpenApi.Models.OpenApiResponses openApiResponses) { } } - public class OpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiAnnotatable, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSchema : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema { public OpenApiSchema() { } - public OpenApiSchema(Microsoft.OpenApi.Models.OpenApiSchema schema) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; set; } + public bool AdditionalPropertiesAllowed { get; set; } + public System.Collections.Generic.IList AllOf { get; set; } public System.Collections.Generic.IDictionary Annotations { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema AdditionalProperties { get; set; } - public virtual bool AdditionalPropertiesAllowed { get; set; } - public virtual System.Collections.Generic.IList AllOf { get; set; } - public virtual System.Collections.Generic.IList AnyOf { get; set; } - public virtual string Comment { get; set; } - public virtual string Const { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Default { get; set; } - public virtual System.Collections.Generic.IDictionary Definitions { get; set; } - public virtual bool Deprecated { get; set; } - public virtual string Description { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } - public virtual string DynamicAnchor { get; set; } - public virtual string DynamicRef { get; set; } - public virtual System.Collections.Generic.IList Enum { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Example { get; set; } - public virtual System.Collections.Generic.IList Examples { get; set; } - public virtual bool? ExclusiveMaximum { get; set; } - public virtual bool? ExclusiveMinimum { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public virtual string Format { get; set; } - public virtual string Id { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Items { get; set; } - public virtual int? MaxItems { get; set; } - public virtual int? MaxLength { get; set; } - public virtual int? MaxProperties { get; set; } - public virtual decimal? Maximum { get; set; } - public virtual int? MinItems { get; set; } - public virtual int? MinLength { get; set; } - public virtual int? MinProperties { get; set; } - public virtual decimal? Minimum { get; set; } - public virtual decimal? MultipleOf { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Not { get; set; } - public virtual bool Nullable { get; set; } - public virtual System.Collections.Generic.IList OneOf { get; set; } - public virtual string Pattern { get; set; } - public virtual System.Collections.Generic.IDictionary PatternProperties { get; set; } - public virtual System.Collections.Generic.IDictionary Properties { get; set; } - public virtual bool ReadOnly { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual System.Collections.Generic.ISet Required { get; set; } - public virtual string Schema { get; set; } - public virtual string Title { get; set; } - public virtual Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } - public virtual bool UnEvaluatedProperties { get; set; } - public virtual bool UnevaluatedProperties { get; set; } - public virtual bool? UniqueItems { get; set; } - public virtual System.Collections.Generic.IDictionary UnrecognizedKeywords { get; set; } - public virtual bool UnresolvedReference { get; set; } - public virtual decimal? V31ExclusiveMaximum { get; set; } - public virtual decimal? V31ExclusiveMinimum { get; set; } - public virtual System.Collections.Generic.IDictionary Vocabulary { get; set; } - public virtual bool WriteOnly { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public System.Collections.Generic.IList AnyOf { get; set; } + public string Comment { get; set; } + public string Const { get; set; } + public System.Text.Json.Nodes.JsonNode Default { get; set; } + public System.Collections.Generic.IDictionary Definitions { get; set; } + public bool Deprecated { get; set; } + public string Description { get; set; } + public Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } + public string DynamicAnchor { get; set; } + public string DynamicRef { get; set; } + public System.Collections.Generic.IList Enum { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; set; } + public System.Collections.Generic.IList Examples { get; set; } + public bool? ExclusiveMaximum { get; set; } + public bool? ExclusiveMinimum { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } + public string Format { get; set; } + public string Id { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; set; } + public int? MaxItems { get; set; } + public int? MaxLength { get; set; } + public int? MaxProperties { get; set; } + public decimal? Maximum { get; set; } + public int? MinItems { get; set; } + public int? MinLength { get; set; } + public int? MinProperties { get; set; } + public decimal? Minimum { get; set; } + public decimal? MultipleOf { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; set; } + public System.Collections.Generic.IList OneOf { get; set; } + public string Pattern { get; set; } + public System.Collections.Generic.IDictionary PatternProperties { get; set; } + public System.Collections.Generic.IDictionary Properties { get; set; } + public bool ReadOnly { get; set; } + public System.Collections.Generic.ISet Required { get; set; } + public string Schema { get; set; } + public string Title { get; set; } + public Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } + public bool UnEvaluatedProperties { get; set; } + public bool UnevaluatedProperties { get; set; } + public bool? UniqueItems { get; set; } + public System.Collections.Generic.IDictionary UnrecognizedKeywords { get; set; } + public decimal? V31ExclusiveMaximum { get; set; } + public decimal? V31ExclusiveMinimum { get; set; } + public System.Collections.Generic.IDictionary Vocabulary { get; set; } + public bool WriteOnly { get; set; } + public Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { public OpenApiSecurityRequirement() { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiSecurityScheme : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiSecurityScheme : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme { public OpenApiSecurityScheme() { } - public OpenApiSecurityScheme(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public bool UnresolvedReference { get; set; } - public virtual string BearerFormat { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; set; } - public virtual Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } - public virtual string Name { get; set; } - public virtual System.Uri OpenIdConnectUrl { get; set; } - public virtual string Scheme { get; set; } - public virtual Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public string BearerFormat { get; set; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; set; } + public Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } + public string Name { get; set; } + public System.Uri OpenIdConnectUrl { get; set; } + public string Scheme { get; set; } + public Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiServer : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -1049,18 +1117,17 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiTag : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiTag : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiReadOnlyDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiTag { public OpenApiTag() { } - public OpenApiTag(Microsoft.OpenApi.Models.OpenApiTag tag) { } - public bool UnresolvedReference { get; set; } - public virtual string Description { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public virtual string Name { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } + public string Name { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiTag CreateShallowCopy() { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiXml : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -1170,45 +1237,44 @@ namespace Microsoft.OpenApi.Models } namespace Microsoft.OpenApi.Models.References { - public abstract class BaseOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public abstract class BaseOpenApiReferenceHolder : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable where T : class, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, V where V : Microsoft.OpenApi.Interfaces.IOpenApiSerializable { protected BaseOpenApiReferenceHolder(Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder source) { } - protected BaseOpenApiReferenceHolder(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, Microsoft.OpenApi.Models.ReferenceType referenceType, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public T Target { get; } - public bool UnresolvedReference { get; set; } + protected BaseOpenApiReferenceHolder(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, Microsoft.OpenApi.Models.ReferenceType referenceType, string externalResource) { } + public virtual T Target { get; } + public bool UnresolvedReference { get; } + public Microsoft.OpenApi.Models.OpenApiReference Reference { get; init; } public abstract V CopyReferenceAsTargetElementWithOverrides(V source); public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiCallbackReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback + public class OpenApiCallbackReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback { - public OpenApiCallbackReference(Microsoft.OpenApi.Models.References.OpenApiCallbackReference callback) { } - public OpenApiCallbackReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public OpenApiCallbackReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } public System.Collections.Generic.IDictionary Extensions { get; } public System.Collections.Generic.Dictionary PathItems { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiExampleReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + public class OpenApiExampleReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { - public OpenApiExampleReference(Microsoft.OpenApi.Models.References.OpenApiExampleReference example) { } - public OpenApiExampleReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public OpenApiExampleReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; } public string ExternalValue { get; } public string Summary { get; set; } public System.Text.Json.Nodes.JsonNode Value { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiExample CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiExample CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiHeaderReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader + public class OpenApiHeaderReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader { - public OpenApiHeaderReference(Microsoft.OpenApi.Models.References.OpenApiHeaderReference header) { } - public OpenApiHeaderReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public OpenApiHeaderReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } public bool AllowEmptyValue { get; } public bool AllowReserved { get; } public System.Collections.Generic.IDictionary Content { get; } @@ -1219,14 +1285,14 @@ namespace Microsoft.OpenApi.Models.References public bool Explode { get; } public System.Collections.Generic.IDictionary Extensions { get; } public bool Required { get; } - public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader CreateShallowCopy() { } } - public class OpenApiLinkReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiLink + public class OpenApiLinkReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiLink { - public OpenApiLinkReference(Microsoft.OpenApi.Models.References.OpenApiLinkReference reference) { } - public OpenApiLinkReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public OpenApiLinkReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; } public string OperationId { get; } @@ -1235,12 +1301,12 @@ namespace Microsoft.OpenApi.Models.References public Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; } public Microsoft.OpenApi.Models.OpenApiServer Server { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiLink CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiLink source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiLink CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiParameterReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter + public class OpenApiParameterReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter { - public OpenApiParameterReference(Microsoft.OpenApi.Models.References.OpenApiParameterReference parameter) { } - public OpenApiParameterReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public OpenApiParameterReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } public bool AllowEmptyValue { get; } public bool AllowReserved { get; } public System.Collections.Generic.IDictionary Content { get; } @@ -1253,13 +1319,14 @@ namespace Microsoft.OpenApi.Models.References public Microsoft.OpenApi.Models.ParameterLocation? In { get; } public string Name { get; } public bool Required { get; } - public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Schema { get; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter CreateShallowCopy() { } } - public class OpenApiPathItemReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement + public class OpenApiPathItemReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { - public OpenApiPathItemReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public OpenApiPathItemReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; } public System.Collections.Generic.IDictionary Operations { get; } @@ -1267,11 +1334,12 @@ namespace Microsoft.OpenApi.Models.References public System.Collections.Generic.IList Servers { get; } public string Summary { get; set; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiRequestBodyReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody + public class OpenApiRequestBodyReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody { - public OpenApiRequestBodyReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public OpenApiRequestBodyReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } public System.Collections.Generic.IDictionary Content { get; } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; } @@ -1279,107 +1347,106 @@ namespace Microsoft.OpenApi.Models.References public Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter ConvertToBodyParameter(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public System.Collections.Generic.IEnumerable ConvertToFormDataParameters(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiResponseReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse + public class OpenApiResponseReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse { - public OpenApiResponseReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public OpenApiResponseReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } public System.Collections.Generic.IDictionary Content { get; } public string Description { get; set; } public System.Collections.Generic.IDictionary Extensions { get; } public System.Collections.Generic.IDictionary Headers { get; } public System.Collections.Generic.IDictionary Links { get; } public override Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse source) { } - } - public class OpenApiSchemaReference : Microsoft.OpenApi.Models.OpenApiSchema, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - { - public OpenApiSchemaReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiSchema? Target { get; } - public override Microsoft.OpenApi.Models.OpenApiSchema AdditionalProperties { get; set; } - public override bool AdditionalPropertiesAllowed { get; set; } - public override System.Collections.Generic.IList AllOf { get; set; } - public override System.Collections.Generic.IList AnyOf { get; set; } - public override string Comment { get; set; } - public override string Const { get; set; } - public override System.Text.Json.Nodes.JsonNode Default { get; set; } - public override System.Collections.Generic.IDictionary Definitions { get; set; } - public override bool Deprecated { get; set; } - public override string Description { get; set; } - public override Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; set; } - public override string DynamicAnchor { get; set; } - public override string DynamicRef { get; set; } - public override System.Collections.Generic.IList Enum { get; set; } - public override System.Text.Json.Nodes.JsonNode Example { get; set; } - public override System.Collections.Generic.IList Examples { get; set; } - public override bool? ExclusiveMaximum { get; set; } - public override bool? ExclusiveMinimum { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public override string Format { get; set; } - public override string Id { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Items { get; set; } - public override int? MaxItems { get; set; } - public override int? MaxLength { get; set; } - public override int? MaxProperties { get; set; } - public override decimal? Maximum { get; set; } - public override int? MinItems { get; set; } - public override int? MinLength { get; set; } - public override int? MinProperties { get; set; } - public override decimal? Minimum { get; set; } - public override decimal? MultipleOf { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Not { get; set; } - public override bool Nullable { get; set; } - public override System.Collections.Generic.IList OneOf { get; set; } - public override string Pattern { get; set; } - public override System.Collections.Generic.IDictionary PatternProperties { get; set; } - public override System.Collections.Generic.IDictionary Properties { get; set; } - public override bool ReadOnly { get; set; } - public override System.Collections.Generic.ISet Required { get; set; } - public override string Schema { get; set; } - public override string Title { get; set; } - public override Microsoft.OpenApi.Models.JsonSchemaType? Type { get; set; } - public override bool UnEvaluatedProperties { get; set; } - public override bool UnevaluatedProperties { get; set; } - public override bool? UniqueItems { get; set; } - public override decimal? V31ExclusiveMaximum { get; set; } - public override decimal? V31ExclusiveMinimum { get; set; } - public override System.Collections.Generic.IDictionary Vocabulary { get; set; } - public override bool WriteOnly { get; set; } - public override Microsoft.OpenApi.Models.OpenApiXml Xml { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse CreateShallowCopy() { } + } + public class OpenApiSchemaReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema + { + public OpenApiSchemaReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema AdditionalProperties { get; } + public bool AdditionalPropertiesAllowed { get; } + public System.Collections.Generic.IList AllOf { get; } + public System.Collections.Generic.IDictionary Annotations { get; } + public System.Collections.Generic.IList AnyOf { get; } + public string Comment { get; } + public string Const { get; } + public System.Text.Json.Nodes.JsonNode Default { get; } + public System.Collections.Generic.IDictionary Definitions { get; } + public bool Deprecated { get; } + public string Description { get; set; } + public Microsoft.OpenApi.Models.OpenApiDiscriminator Discriminator { get; } + public string DynamicAnchor { get; } + public string DynamicRef { get; } + public System.Collections.Generic.IList Enum { get; } + public System.Text.Json.Nodes.JsonNode Example { get; } + public System.Collections.Generic.IList Examples { get; } + public bool? ExclusiveMaximum { get; } + public bool? ExclusiveMinimum { get; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + public string Format { get; } + public string Id { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Items { get; } + public int? MaxItems { get; } + public int? MaxLength { get; } + public int? MaxProperties { get; } + public decimal? Maximum { get; } + public int? MinItems { get; } + public int? MinLength { get; } + public int? MinProperties { get; } + public decimal? Minimum { get; } + public decimal? MultipleOf { get; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema Not { get; } + public System.Collections.Generic.IList OneOf { get; } + public string Pattern { get; } + public System.Collections.Generic.IDictionary PatternProperties { get; } + public System.Collections.Generic.IDictionary Properties { get; } + public bool ReadOnly { get; } + public System.Collections.Generic.ISet Required { get; } + public string Schema { get; } + public string Title { get; } + public Microsoft.OpenApi.Models.JsonSchemaType? Type { get; } + public bool UnEvaluatedProperties { get; } + public bool UnevaluatedProperties { get; } + public bool? UniqueItems { get; } + public System.Collections.Generic.IDictionary UnrecognizedKeywords { get; } + public decimal? V31ExclusiveMaximum { get; } + public decimal? V31ExclusiveMinimum { get; } + public System.Collections.Generic.IDictionary Vocabulary { get; } + public bool WriteOnly { get; } + public Microsoft.OpenApi.Models.OpenApiXml Xml { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiSecuritySchemeReference : Microsoft.OpenApi.Models.OpenApiSecurityScheme, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable - { - public OpenApiSecuritySchemeReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } - public Microsoft.OpenApi.Models.OpenApiSecurityScheme Target { get; } - public override string BearerFormat { get; set; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; set; } - public override Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } - public override string Name { get; set; } - public override System.Uri OpenIdConnectUrl { get; set; } - public override string Scheme { get; set; } - public override Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; set; } - public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public class OpenApiSecuritySchemeReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme + { + public OpenApiSecuritySchemeReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public string BearerFormat { get; } + public string Description { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.OpenApiOAuthFlows Flows { get; } + public Microsoft.OpenApi.Models.ParameterLocation? In { get; } + public string Name { get; } + public System.Uri OpenIdConnectUrl { get; } + public string Scheme { get; } + public Microsoft.OpenApi.Models.SecuritySchemeType? Type { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme CreateShallowCopy() { } } - public class OpenApiTagReference : Microsoft.OpenApi.Models.OpenApiTag, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiTagReference : Microsoft.OpenApi.Models.References.BaseOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Interfaces.IShallowCopyable, Microsoft.OpenApi.Models.Interfaces.IOpenApiReadOnlyDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiTag { - public OpenApiTagReference(Microsoft.OpenApi.Models.References.OpenApiTagReference source) { } - public OpenApiTagReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public Microsoft.OpenApi.Models.OpenApiTag Target { get; } - public override string Description { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } - public override string Name { get; set; } - public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public OpenApiTagReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument = null, string externalResource = null) { } + public string Description { get; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; } + public string Name { get; } + public override Microsoft.OpenApi.Models.OpenApiTag Target { get; } + public override Microsoft.OpenApi.Models.Interfaces.IOpenApiTag CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiTag source) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiTag CreateShallowCopy() { } } } namespace Microsoft.OpenApi.Reader @@ -1396,7 +1463,7 @@ namespace Microsoft.OpenApi.Reader { public OpenApiJsonReader() { } public Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings) { } - public Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null) { } + public Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings) { } public System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, System.Threading.CancellationToken cancellationToken = default) { } public T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, Microsoft.OpenApi.Models.OpenApiDocument openApiDocument, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } @@ -1567,6 +1634,8 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme securityScheme) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } @@ -1579,9 +1648,7 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiServer server) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiServerVariable serverVariable) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiTag tag) { } @@ -1666,6 +1733,8 @@ namespace Microsoft.OpenApi.Validations public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiPathItem pathItem) { } public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiRequestBody requestBody) { } public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiResponse response) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiSecurityScheme securityScheme) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } @@ -1678,9 +1747,7 @@ namespace Microsoft.OpenApi.Validations public override void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiServer server) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiServerVariable serverVariable) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiTag tag) { } @@ -1784,7 +1851,7 @@ namespace Microsoft.OpenApi.Validations.Rules public static Microsoft.OpenApi.Validations.ValidationRule HeaderMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule MediaTypeMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule ParameterMismatchedDataType { get; } - public static Microsoft.OpenApi.Validations.ValidationRule SchemaMismatchedDataType { get; } + public static Microsoft.OpenApi.Validations.ValidationRule SchemaMismatchedDataType { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiOAuthFlowRules @@ -1823,9 +1890,9 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiSchemaRules { - public static Microsoft.OpenApi.Validations.ValidationRule ValidateSchemaDiscriminator { get; } - public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList childSchema) { } - public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.Models.OpenApiSchema schema, string discriminatorName) { } + public static Microsoft.OpenApi.Validations.ValidationRule ValidateSchemaDiscriminator { get; } + public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList childSchema) { } + public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.Models.Interfaces.IOpenApiSchema schema, string discriminatorName) { } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiServerRules diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs index 96afcb301..05b4bb62c 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs @@ -20,7 +20,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() var mediaType = new OpenApiMediaType { Example = 55, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -47,10 +47,10 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() var mediaType = new OpenApiMediaType { - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer, } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs index 13328046e..721445e23 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs @@ -71,7 +71,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() In = ParameterLocation.Path, Required = true, Example = 55, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -99,10 +99,10 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer, } @@ -159,7 +159,7 @@ public void PathParameterNotInThePathShouldReturnAnError() Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } @@ -194,7 +194,7 @@ public void PathParameterInThePathShouldBeOk() Name = "parameter1", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String, } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs index de9d58443..b9a73da40 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiReferenceValidationTests.cs @@ -6,6 +6,8 @@ using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Validations; using Xunit; @@ -21,17 +23,12 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() var sharedSchema = new OpenApiSchema { Type = JsonSchemaType.String, - Reference = new() - { - Id = "test" - }, - UnresolvedReference = false }; var document = new OpenApiDocument(); document.Components = new() { - Schemas = new Dictionary() + Schemas = new Dictionary() { ["test"] = sharedSchema } @@ -53,7 +50,7 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() { ["application/json"] = new() { - Schema = sharedSchema + Schema = new OpenApiSchemaReference("test") } } } @@ -66,8 +63,8 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() // Act var rules = new Dictionary>() { - { typeof(OpenApiSchema), - new List() { new AlwaysFailRule() } + { typeof(IOpenApiSchema), + new List() { new AlwaysFailRule() } } }; @@ -75,7 +72,7 @@ public void ReferencedSchemaShouldOnlyBeValidatedOnce() // Assert - Assert.True(errors.Count() == 1); + Assert.Single(errors); } [Fact] @@ -86,14 +83,10 @@ public void UnresolvedSchemaReferencedShouldNotBeValidated() var sharedSchema = new OpenApiSchema { Type = JsonSchemaType.String, - Reference = new() - { - Id = "test" - }, - UnresolvedReference = true }; var document = new OpenApiDocument(); + document.AddComponent("test", sharedSchema); document.Paths = new() { @@ -111,7 +104,7 @@ public void UnresolvedSchemaReferencedShouldNotBeValidated() { ["application/json"] = new() { - Schema = sharedSchema + Schema = new OpenApiSchemaReference("test") } } } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs index 9edd57c1e..d8820defc 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs @@ -7,6 +7,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Validations.Rules; @@ -89,7 +90,7 @@ public void ValidateEnumShouldNotHaveDataTypeMismatchForSimpleSchema() }).Node }, Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Integer } @@ -111,39 +112,38 @@ public void ValidateEnumShouldNotHaveDataTypeMismatchForSimpleSchema() public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() { // Arrange - IEnumerable warnings; var schema = new OpenApiSchema { Type = JsonSchemaType.Object, Properties = { - ["property1"] = new() + ["property1"] = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Integer, Format = "int64" } }, - ["property2"] = new() + ["property2"] = new OpenApiSchema() { Type = JsonSchemaType.Array, - Items = new() + Items = new OpenApiSchema() { Type = JsonSchemaType.Object, - AdditionalProperties = new() + AdditionalProperties = new OpenApiSchema() { Type = JsonSchemaType.Boolean } } }, - ["property3"] = new() + ["property3"] = new OpenApiSchema() { Type = JsonSchemaType.String, Format = "password" }, - ["property4"] = new() + ["property4"] = new OpenApiSchema() { Type = JsonSchemaType.String } @@ -173,22 +173,18 @@ public void ValidateDefaultShouldNotHaveDataTypeMismatchForComplexSchema() // Act var defaultRuleSet = ValidationRuleSet.GetDefaultRuleSet(); - defaultRuleSet.Add(typeof(OpenApiSchema), OpenApiNonDefaultRules.SchemaMismatchedDataType); + defaultRuleSet.Add(typeof(IOpenApiSchema), OpenApiNonDefaultRules.SchemaMismatchedDataType); var validator = new OpenApiValidator(defaultRuleSet); var walker = new OpenApiWalker(validator); - walker.Walk(schema); - - warnings = validator.Warnings; - bool result = !warnings.Any(); + walker.Walk((IOpenApiSchema)schema); // Assert - Assert.False(result); + Assert.NotEmpty(validator.Warnings); } [Fact] public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator() { - IEnumerable errors; var components = new OpenApiComponents { Schemas = { @@ -198,7 +194,6 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD { Type = JsonSchemaType.Object, Discriminator = new() { PropertyName = "property1" }, - Reference = new() { Id = "schema1" } } } } @@ -208,17 +203,14 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD var walker = new OpenApiWalker(validator); walker.Walk(components); - errors = validator.Errors; - var result = !errors.Any(); - // Assert - Assert.False(result); + Assert.NotEmpty(validator.Errors); Assert.Equivalent(new List { new OpenApiValidatorError(nameof(OpenApiSchemaRules.ValidateSchemaDiscriminator),"#/schemas/schema1/discriminator", string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator, - "schema1", "property1")) - }, errors); + string.Empty, "property1")) + }, validator.Errors); } [Fact] @@ -238,9 +230,9 @@ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscrim { PropertyName = "type" }, - OneOf = new List + OneOf = new List { - new() + new OpenApiSchema() { Properties = { @@ -252,14 +244,8 @@ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscrim } } }, - Reference = new() - { - Type = ReferenceType.Schema, - Id = "Person" - } } }, - Reference = new() { Id = "Person" } } } } diff --git a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs index fbe0abf14..581f2998a 100644 --- a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs @@ -43,7 +43,7 @@ public void ExpectedVirtualsInvolved() visitor.Visit(default(IDictionary)); visitor.Visit(default(OpenApiComponents)); visitor.Visit(default(OpenApiExternalDocs)); - visitor.Visit(default(OpenApiSchema)); + visitor.Visit(default(IOpenApiSchema)); visitor.Visit(default(IDictionary)); visitor.Visit(default(IOpenApiLink)); visitor.Visit(default(IOpenApiCallback)); @@ -51,7 +51,7 @@ public void ExpectedVirtualsInvolved() visitor.Visit(default(IOpenApiHeader)); visitor.Visit(default(OpenApiOAuthFlow)); visitor.Visit(default(OpenApiSecurityRequirement)); - visitor.Visit(default(OpenApiSecurityScheme)); + visitor.Visit(default(IOpenApiSecurityScheme)); visitor.Visit(default(IOpenApiExample)); visitor.Visit(default(IList)); visitor.Visit(default(IList)); @@ -232,7 +232,7 @@ public override void Visit(OpenApiExternalDocs externalDocs) base.Visit(externalDocs); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { EncodeCall(); base.Visit(schema); @@ -280,7 +280,7 @@ public override void Visit(OpenApiSecurityRequirement securityRequirement) base.Visit(securityRequirement); } - public override void Visit(OpenApiSecurityScheme securityScheme) + public override void Visit(IOpenApiSecurityScheme securityScheme) { EncodeCall(); base.Visit(securityScheme); diff --git a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs index c4ed91658..ce45186c6 100644 --- a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; @@ -121,9 +122,9 @@ public void WalkDOMWithCycles() var loopySchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { - ["name"] = new() { Type = JsonSchemaType.String } + ["name"] = new OpenApiSchema() { Type = JsonSchemaType.String } } }; @@ -133,7 +134,7 @@ public void WalkDOMWithCycles() { Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { ["loopy"] = loopySchema } @@ -161,24 +162,18 @@ public void WalkDOMWithCycles() [Fact] public void LocateReferences() { - var baseSchema = new OpenApiSchemaReference("base", null); + var baseSchema = new OpenApiSchema(); var derivedSchema = new OpenApiSchema { - AnyOf = new List { baseSchema }, - Reference = new() - { - Id = "derived", - Type = ReferenceType.Schema - }, - UnresolvedReference = false + AnyOf = new List { new OpenApiSchemaReference("base") }, }; var testHeader = new OpenApiHeader() { - Schema = derivedSchema, + Schema = new OpenApiSchemaReference("derived"), }; - var testHeaderReference = new OpenApiHeaderReference(testHeader, "test-header"); + var testHeaderReference = new OpenApiHeaderReference("test-header"); var doc = new OpenApiDocument { @@ -198,7 +193,7 @@ public void LocateReferences() { ["application/json"] = new() { - Schema = derivedSchema + Schema = new OpenApiSchemaReference("derived") } }, Headers = @@ -213,7 +208,7 @@ public void LocateReferences() }, Components = new() { - Schemas = new Dictionary + Schemas = new Dictionary { ["derived"] = derivedSchema, ["base"] = baseSchema, @@ -222,9 +217,9 @@ public void LocateReferences() { ["test-header"] = testHeader }, - SecuritySchemes = new Dictionary + SecuritySchemes = new Dictionary { - ["test-secScheme"] = new OpenApiSecuritySchemeReference("reference-to-scheme", null, null) + ["test-secScheme"] = new OpenApiSecuritySchemeReference("reference-to-scheme") } } }; @@ -239,7 +234,7 @@ public void LocateReferences() "referenceAt: #/components/schemas/derived/anyOf/0", "referenceAt: #/components/securitySchemes/test-secScheme", "referenceAt: #/components/headers/test-header/schema" - }, locator.Locations.Where(l => l.StartsWith("referenceAt:"))); + }, locator.Locations.Where(l => l.StartsWith("referenceAt:", StringComparison.OrdinalIgnoreCase))); } } @@ -305,7 +300,7 @@ public override void Visit(OpenApiMediaType mediaType) Locations.Add(this.PathString); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { Locations.Add(this.PathString); } diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs index 14e017fe9..8c5478cf7 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Xunit; @@ -15,6 +16,11 @@ public class OpenApiWorkspaceTests [Fact] public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() { + var testSchema = new OpenApiSchema() + { + Type = JsonSchemaType.String, + Description = "The referenced one" + }; var doc = new OpenApiDocument() { Paths = new OpenApiPaths() @@ -33,14 +39,7 @@ public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() { ["application/json"] = new OpenApiMediaType() { - Schema = new() - { - Reference = new() - { - Id = "test", - Type = ReferenceType.Schema - } - } + Schema = new OpenApiSchemaReference("test") } } } @@ -56,11 +55,7 @@ public void OpenApiWorkspacesCanAddComponentsFromAnotherDocument() Components = new OpenApiComponents() { Schemas = { - ["test"] = new() - { - Type = JsonSchemaType.String, - Description = "The referenced one" - } + ["test"] = testSchema } } }; @@ -76,7 +71,8 @@ public void OpenApiWorkspacesCanResolveExternalReferences() var workspace = new OpenApiWorkspace(); var externalDoc = CreateCommonDocument(); - workspace.RegisterComponent("https://everything.json/common#/components/schemas/test", externalDoc.Components.Schemas["test"]); + var castSchema = Assert.IsType(externalDoc.Components.Schemas["test"]); + workspace.RegisterComponent("https://everything.json/common#/components/schemas/test", castSchema); var schema = workspace.ResolveReference("https://everything.json/common#/components/schemas/test"); @@ -135,7 +131,7 @@ private static OpenApiDocument CreateCommonDocument() { Schemas = { - ["test"] = new() + ["test"] = new OpenApiSchema() { Type = JsonSchemaType.String, Description = "The referenced one" diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs index a26173606..2e05a70a3 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiWriterAnyExtensionsTests.cs @@ -113,7 +113,7 @@ public async Task WriteOpenApiFloatAsJsonWorksAsync(float input, bool produceTer var json = await WriteAsJsonAsync(floatValue, produceTerseOutput); // Assert - Assert.Equal(input.ToString(), json); + Assert.Equal(input.ToString(CultureInfo.InvariantCulture), json); } public static IEnumerable DoubleInputs @@ -141,7 +141,7 @@ public async Task WriteOpenApiDoubleAsJsonWorksAsync(double input, bool produceT var json = await WriteAsJsonAsync(doubleValue, produceTerseOutput); // Assert - Assert.Equal(input.ToString(), json); + Assert.Equal(input.ToString(CultureInfo.InvariantCulture), json); } public static IEnumerable StringifiedDateTimes @@ -149,7 +149,7 @@ public static IEnumerable StringifiedDateTimes get { return - from input in new [] { + from input in new[] { "2017-1-2", "1999-01-02T12:10:22", "1999-01-03", @@ -178,7 +178,7 @@ public async Task WriteOpenApiDateTimeAsJsonWorksAsync(string inputString, bool public static IEnumerable BooleanInputs { get => - from input in new [] { true, false } + from input in new[] { true, false } from shouldBeTerse in shouldProduceTerseOutputValues select new object[] { input, shouldBeTerse }; } @@ -258,7 +258,7 @@ private static async Task WriteAsJsonAsync(JsonNode any, bool produceTer // Arrange (continued) using var stream = new MemoryStream(); var writer = new OpenApiJsonWriter( - new StreamWriter(stream), + new CultureInvariantStreamWriter(stream), new() { Terse = produceTerseOutput }); writer.WriteAny(any); @@ -279,5 +279,15 @@ private static async Task WriteAsJsonAsync(JsonNode any, bool produceTer _ => value.MakeLineBreaksEnvironmentNeutral(), }; } + + private class CultureInvariantStreamWriter : StreamWriter + { + public CultureInvariantStreamWriter(Stream stream) : base(stream) + { + } + + public override IFormatProvider FormatProvider => CultureInfo.InvariantCulture; + } + } } diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs index f10dba764..669f4cb13 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs @@ -8,6 +8,7 @@ using System.IO; using System.Threading.Tasks; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using Xunit; @@ -441,12 +442,6 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() var thingSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - UnresolvedReference = false, - Reference = new() - { - Id = "thing", - Type = ReferenceType.Schema - } }; var doc = new OpenApiDocument() @@ -468,10 +463,10 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() { Description = "OK", Content = { - ["application/json"] = new() - { - Schema = thingSchema - } + ["application/json"] = new() + { + Schema = new OpenApiSchemaReference("thing") + } } } } @@ -485,6 +480,8 @@ private static OpenApiDocument CreateDocWithSimpleSchemaToInline() ["thing"] = thingSchema} } }; + doc.RegisterComponents(); + doc.SetReferenceHostDocument(); return doc; }