diff --git a/docs/x-ms-parameter-location.md b/docs/x-ms-parameter-location.md new file mode 100644 index 000000000..629a6ea01 --- /dev/null +++ b/docs/x-ms-parameter-location.md @@ -0,0 +1,15 @@ +# XmsParameterLocation +## Description +An Open API Document has a section for parameters. Any parameter that is defined in this (global) parameters section will be treated as client parameters(by autorest). So, the service teams must be absolutely sure that this is the expectation (i.e. defining them as client properties) before defining the parameters in this section. + +90% scenario is that subscriptionId and api-version are parameters that should be defined in the global parameters section. + +However, one can define a parameter that is being referenced in multiple operations (example: resourceGroupName) in the global parameters section and apply the extension "x-ms-parameter-location": "method". This will then not be a client property. + +So, when you define a parameter in the global parameters section, apply the extension "x-ms-parameter-location": "method" so this will not be treated as a client property. But, if you actually want the parameter to be client properties then apply the extension "x-ms-parameter-location": "client". + +## How to fix +Apply "x-ms-parameter-location": "method"/"x-ms-parameter-location": "client" on the global parameters (based on your requirements) + +## Reference +Refer [Link](https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-parameter-location) for further details. \ No newline at end of file diff --git a/src/dotnet/OpenAPI.Validator.Tests/OpenAPIModelerValidationTests.cs b/src/dotnet/OpenAPI.Validator.Tests/OpenAPIModelerValidationTests.cs index f30d43677..5d2561097 100644 --- a/src/dotnet/OpenAPI.Validator.Tests/OpenAPIModelerValidationTests.cs +++ b/src/dotnet/OpenAPI.Validator.Tests/OpenAPIModelerValidationTests.cs @@ -14,7 +14,7 @@ namespace OpenAPI.Validator.Tests { - + [Collection("Validation Tests")] public partial class OpenAPIModelerValidationTests { @@ -98,6 +98,13 @@ public void AnonymousParameterSchemaValidation() Assert.Equal(messages.Count(), 1); } + [Fact] + public void XmsParameterLocationValidation() + { + var messages = GetValidationMessagesForRule("xms-parameter-location.json"); + Assert.Equal(messages.Count(), 1); + } + [Fact] public void OperationParametersValidation() { @@ -638,7 +645,7 @@ public void LocationPropertyWithoutXmsMutability() var messages = GetValidationMessagesForRule("location-without-xms-mutability.json"); Assert.Equal(messages.Count(), 1); } - + [Fact] public void LocationPropertyWithIncorrectXmsMutability() { diff --git a/src/dotnet/OpenAPI.Validator.Tests/Resource/OpenAPI/Validation/positive/clean-complex-spec.json b/src/dotnet/OpenAPI.Validator.Tests/Resource/OpenAPI/Validation/positive/clean-complex-spec.json index 1c5df9464..0ae0e75a8 100644 --- a/src/dotnet/OpenAPI.Validator.Tests/Resource/OpenAPI/Validation/positive/clean-complex-spec.json +++ b/src/dotnet/OpenAPI.Validator.Tests/Resource/OpenAPI/Validation/positive/clean-complex-spec.json @@ -36,9 +36,7 @@ "description": "foo", "operationId": "Operations_List", "x-ms-examples": { - "Get operations": { - - } + "Get operations": {} }, "parameters": [ { @@ -75,9 +73,7 @@ "pets" ], "x-ms-examples": { - "The pet we get": { - - } + "The pet we get": {} }, "parameters": [ { @@ -118,9 +114,7 @@ "pets" ], "x-ms-examples": { - "The pet we post": { - - } + "The pet we post": {} }, "responses": { "201": { @@ -144,9 +138,7 @@ "pets" ], "x-ms-examples": { - "The pet we get": { - - } + "The pet we get": {} }, "parameters": [ { @@ -177,9 +169,7 @@ "get": { "operationId": "Foos_Get", "x-ms-examples": { - "The foo we get": { - - } + "The foo we get": {} }, "description": "foo", "responses": { @@ -192,9 +182,7 @@ "operationId": "Foos_Post", "description": "foo", "x-ms-examples": { - "The foo we post": { - - } + "The foo we post": {} }, "parameters": [ { @@ -224,9 +212,7 @@ "operationId": "Foos_PostOverload", "description": "foo", "x-ms-examples": { - "The foo we post": { - - } + "The foo we post": {} }, "parameters": [ { @@ -255,7 +241,8 @@ "in": "query", "name": "FooQueryParam", "description": "Query parameter for Foo operation", - "type": "string" + "type": "string", + "x-ms-parameter-location": "method" }, "SubscriptionIdParameter": { "name": "subscriptionId", diff --git a/src/dotnet/OpenAPI.Validator.Tests/Resource/OpenAPI/Validation/xms-parameter-location.json b/src/dotnet/OpenAPI.Validator.Tests/Resource/OpenAPI/Validation/xms-parameter-location.json new file mode 100644 index 000000000..505daf63e --- /dev/null +++ b/src/dotnet/OpenAPI.Validator.Tests/Resource/OpenAPI/Validation/xms-parameter-location.json @@ -0,0 +1,148 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft Azure Redis Cache Management API", + "description": "Some cool documentation.", + "version": "2014-04-01-preview" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "basePath": "/", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}": { + "delete": { + "tags": [ + "Redis" + ], + "operationId": "Redis_Delete", + "description": "Deletes a Redis cache.", + "x-ms-long-running-operation": true, + "parameters": [ + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group." + }, + { + "name": "name", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the Redis cache." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParamterer" + } + ], + "responses": { + "200": { + "description": "" + }, + "204": { + "description": "" + } + } + } + } + }, + "definitions": { + "Sku": { + "description": "The SKU (pricing tier) of the CDN profile.", + "type": "object", + "properties": { + "name": { + "$ref": "#/definitions/SkuName", + "description": "The name." + } + } + }, + "SkuName": { + "type": "string", + "enum": [ + "NotSpecified", + "Free", + "Shared", + "Basic", + "Standard", + "Premium" + ], + "x-ms-enum": { + "name": "SkuName", + "modelAsString": false + }, + "description": "The sku name." + }, + "Resource": { + "description": "The Resource model definition.", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "x-ms-client-name": "id2", + "description": "Resource Id" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "Resource name" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "Resource type" + }, + "location": { + "type": "string", + "description": "Resource location" + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Resource tags" + } + }, + "required": [ + "location" + ], + "x-ms-azure-resource": true + } + }, + "parameters": { + "SubscriptionIdParamterer": { + "name": "subscriptionId", + "in": "path", + "description": "Subscription ID.", + "required": true, + "type": "string" + }, + "ApiVersionParameter": { + "name": "apiVersion", + "in": "path", + "description": "API ID.", + "required": true, + "type": "string" + }, + "CatalogNameParameter": { + "name": "catalogName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the data catlog in the specified subscription and resource group." + } + } +} \ No newline at end of file diff --git a/src/dotnet/OpenAPI.Validator/Model/ServiceDefinition.cs b/src/dotnet/OpenAPI.Validator/Model/ServiceDefinition.cs index ba98bcb91..7f38a6f00 100644 --- a/src/dotnet/OpenAPI.Validator/Model/ServiceDefinition.cs +++ b/src/dotnet/OpenAPI.Validator/Model/ServiceDefinition.cs @@ -127,6 +127,7 @@ public ServiceDefinition() /// [Rule(typeof(ParameterNotDefinedInGlobalParameters))] [CollectionRule(typeof(AnonymousBodyParameter))] + [CollectionRule(typeof(XmsParameterLocation))] public Dictionary Parameters { get; set; } /// diff --git a/src/dotnet/OpenAPI.Validator/Properties/Resources.Designer.cs b/src/dotnet/OpenAPI.Validator/Properties/Resources.Designer.cs index 76867be0d..086c6b5df 100644 --- a/src/dotnet/OpenAPI.Validator/Properties/Resources.Designer.cs +++ b/src/dotnet/OpenAPI.Validator/Properties/Resources.Designer.cs @@ -8,11 +8,12 @@ // //------------------------------------------------------------------------------ -namespace OpenAPI.Validator.Properties { +namespace OpenAPI.Validator.Properties +{ using System; using System.Reflection; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -23,762 +24,941 @@ namespace OpenAPI.Validator.Properties { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - + internal class Resources + { + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { + internal Resources() + { } - + /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if (object.ReferenceEquals(resourceMan, null)) + { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenAPI.Validator.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly); resourceMan = temp; } return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { + internal static global::System.Globalization.CultureInfo Culture + { + get + { return resourceCulture; } - set { + set + { resourceCulture = value; } } - + /// /// Looks up a localized string similar to Top level properties should be one of name, type, id, location, properties, tags, plan, sku, etag, managedBy, identity, zones. Model definition '{0}' has extra properties ['{1}'].. /// - internal static string AllowedTopLevelProperties { - get { + internal static string AllowedTopLevelProperties + { + get + { return ResourceManager.GetString("AllowedTopLevelProperties", resourceCulture); } } - + /// /// Looks up a localized string similar to Inline/anonymous models must not be used, instead define a schema with a model name in the "definitions" section and refer to it. This allows operations to share the models.. /// - internal static string AnonymousTypesDiscouraged { - get { + internal static string AnonymousTypesDiscouraged + { + get + { return ResourceManager.GetString("AnonymousTypesDiscouraged", resourceCulture); } } - + /// /// Looks up a localized string similar to API Version must be in the format: yyyy-MM-dd, optionally followed by -preview, -alpha, -beta, -rc, -privatepreview.. /// - internal static string APIVersionFormatIsNotValid { - get { + internal static string APIVersionFormatIsNotValid + { + get + { return ResourceManager.GetString("APIVersionFormatIsNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to Top level property names should not be repeated inside the properties bag for ARM resource '{0}'. Properties [{1}] conflict with ARM top level properties. Please rename these.. /// - internal static string ArmPropertiesBagValidationMessage { - get { + internal static string ArmPropertiesBagValidationMessage + { + get + { return ResourceManager.GetString("ArmPropertiesBagValidationMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to Property named: '{0}', must follow camelCase style. Example: '{1}'.. /// - internal static string BodyPropertyNameCamelCase { - get { + internal static string BodyPropertyNameCamelCase + { + get + { return ResourceManager.GetString("BodyPropertyNameCamelCase", resourceCulture); } } - + /// /// Looks up a localized string similar to Booleans are not descriptive and make them hard to use. Consider using string enums with allowed set of values defined. Property: {0}. /// - internal static string BooleanPropertyNotRecommended { - get { + internal static string BooleanPropertyNotRecommended + { + get + { return ResourceManager.GetString("BooleanPropertyNotRecommended", resourceCulture); } } - + /// /// Looks up a localized string similar to Found a type set '{0}' which is circularly defined.. /// - internal static string CircularBaseSchemaSet { - get { + internal static string CircularBaseSchemaSet + { + get + { return ResourceManager.GetString("CircularBaseSchemaSet", resourceCulture); } } - + /// /// Looks up a localized string similar to Circular reference detected: {0}. /// - internal static string CircularReference { - get { + internal static string CircularReference + { + get + { return ResourceManager.GetString("CircularReference", resourceCulture); } } - + /// /// Looks up a localized string similar to Collection object '{0}' returned by list operation '{1}' with 'x-ms-pageable' extension, has no property named 'value'.. /// - internal static string CollectionObjectPropertiesNamingMessage { - get { + internal static string CollectionObjectPropertiesNamingMessage + { + get + { return ResourceManager.GetString("CollectionObjectPropertiesNamingMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to Reference specifies the definition {0} that does not exist.. /// - internal static string DefinitionDoesNotExist { - get { + internal static string DefinitionDoesNotExist + { + get + { return ResourceManager.GetString("DefinitionDoesNotExist", resourceCulture); } } - + /// /// Looks up a localized string similar to Property named: '{0}', for definition: '{1}' must follow camelCase style. Example: '{2}'.. /// - internal static string DefinitionsPropertiesNameCamelCase { - get { + internal static string DefinitionsPropertiesNameCamelCase + { + get + { return ResourceManager.GetString("DefinitionsPropertiesNameCamelCase", resourceCulture); } } - + /// /// Looks up a localized string similar to 'Delete' operation '{0}' must not have a request body.. /// - internal static string DeleteMustNotHaveRequestBody { - get { + internal static string DeleteMustNotHaveRequestBody + { + get + { return ResourceManager.GetString("DeleteMustNotHaveRequestBody", resourceCulture); } } - + /// /// Looks up a localized string similar to 'DELETE' operation '{0}' should use method name 'Delete'. Note: If you have already shipped an SDK on top of this spec, fixing this warning may introduce a breaking change.. /// - internal static string DeleteOperationNameNotValid { - get { + internal static string DeleteOperationNameNotValid + { + get + { return ResourceManager.GetString("DeleteOperationNameNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to The value provided for description is not descriptive enough. Accurate and descriptive description is essential for maintaining reference documentation.. /// - internal static string DescriptionNotDescriptive { - get { + internal static string DescriptionNotDescriptive + { + get + { return ResourceManager.GetString("DescriptionNotDescriptive", resourceCulture); } } - + /// /// Looks up a localized string similar to Found operation objects with duplicate operationId '{0}'. OperationId must be unique among all operations described in the API.. /// - internal static string DuplicateOperationIdException { - get { + internal static string DuplicateOperationIdException + { + get + { return ResourceManager.GetString("DuplicateOperationIdException", resourceCulture); } } - + /// /// Looks up a localized string similar to Empty x-ms-client-name property.. /// - internal static string EmptyClientName { - get { + internal static string EmptyClientName + { + get + { return ResourceManager.GetString("EmptyClientName", resourceCulture); } } - + /// /// Looks up a localized string similar to Error parsing swagger file. /// - internal static string ErrorParsingSpec { - get { + internal static string ErrorParsingSpec + { + get + { return ResourceManager.GetString("ErrorParsingSpec", resourceCulture); } } - + /// /// Looks up a localized string similar to Reached Maximum reference depth when resolving reference '{0}'.. /// - internal static string ExceededMaximumReferenceDepth { - get { + internal static string ExceededMaximumReferenceDepth + { + get + { return ResourceManager.GetString("ExceededMaximumReferenceDepth", resourceCulture); } } - + /// /// Looks up a localized string similar to Generating client model from swagger model.. /// - internal static string GeneratingClient { - get { + internal static string GeneratingClient + { + get + { return ResourceManager.GetString("GeneratingClient", resourceCulture); } } - + /// /// Looks up a localized string similar to 'GET' operation '{0}' should use method name 'Get' or Method name start with 'List'. Note: If you have already shipped an SDK on top of this spec, fixing this warning may introduce a breaking change.. /// - internal static string GetOperationNameNotValid { - get { + internal static string GetOperationNameNotValid + { + get + { return ResourceManager.GetString("GetOperationNameNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to Guid used in model definition '{1}' for property '{0}'. Usage of Guid is not recommanded. If GUIDs are absolutely required in your service, please get sign off from the Azure API review board.. /// - internal static string GuidUsageNotRecommended { - get { + internal static string GuidUsageNotRecommended + { + get + { return ResourceManager.GetString("GuidUsageNotRecommended", resourceCulture); } } - + /// /// Looks up a localized string similar to Permissible values for HTTP Verb are delete,get,put,patch,head,options,post. . /// - internal static string HttpVerbIsNotValid { - get { + internal static string HttpVerbIsNotValid + { + get + { return ResourceManager.GetString("HttpVerbIsNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to Found incompatible property types {1}, {2} for property '{0}' in schema inheritance chain {3}. /// - internal static string IncompatibleTypesInBaseSchema { - get { + internal static string IncompatibleTypesInBaseSchema + { + get + { return ResourceManager.GetString("IncompatibleTypesInBaseSchema", resourceCulture); } } - + /// /// Looks up a localized string similar to Found incompatible property types {1}, {2} for property '{0}' in schema {3}. /// - internal static string IncompatibleTypesInSchemaComposition { - get { + internal static string IncompatibleTypesInSchemaComposition + { + get + { return ResourceManager.GetString("IncompatibleTypesInSchemaComposition", resourceCulture); } } - + /// /// Looks up a localized string similar to Swagger specification is missing info section. /// - internal static string InfoSectionMissing { - get { + internal static string InfoSectionMissing + { + get + { return ResourceManager.GetString("InfoSectionMissing", resourceCulture); } } - + /// /// Looks up a localized string similar to Input parameter is required.. /// - internal static string InputRequired { - get { + internal static string InputRequired + { + get + { return ResourceManager.GetString("InputRequired", resourceCulture); } } - + /// /// Looks up a localized string similar to The schema's '{0}' ancestors should have at lease one property. /// - internal static string InvalidAncestors { - get { + internal static string InvalidAncestors + { + get + { return ResourceManager.GetString("InvalidAncestors", resourceCulture); } } - + /// /// Looks up a localized string similar to Collection format '{0}' is not a valid collection format (in parameter '{1}').. /// - internal static string InvalidCollectionFormat { - get { + internal static string InvalidCollectionFormat + { + get + { return ResourceManager.GetString("InvalidCollectionFormat", resourceCulture); } } - + /// /// Looks up a localized string similar to The default value is not one of the values enumerated as valid for this element.. /// - internal static string InvalidDefault { - get { + internal static string InvalidDefault + { + get + { return ResourceManager.GetString("InvalidDefault", resourceCulture); } } - + /// /// Looks up a localized string similar to When property is modeled as "readOnly": true then x-ms-mutability extension can only have "read" value. When property is modeled as "readOnly": false then applying x-ms-mutability extension with only "read" value is not allowed. Extension contains invalid values: '{0}'.. /// - internal static string InvalidMutabilityValueForReadOnly { - get { + internal static string InvalidMutabilityValueForReadOnly + { + get + { return ResourceManager.GetString("InvalidMutabilityValueForReadOnly", resourceCulture); } } - + /// /// Looks up a localized string similar to Cannot use 'extend' property with 'allOf' property in schema {0}. /// - internal static string InvalidTypeExtendsWithAllOf { - get { + internal static string InvalidTypeExtendsWithAllOf + { + get + { return ResourceManager.GetString("InvalidTypeExtendsWithAllOf", resourceCulture); } } - + /// /// Looks up a localized string similar to '{0}' is not implemented in SwaggerSchema.ToType extension method.. /// - internal static string InvalidTypeInSwaggerSchema { - get { + internal static string InvalidTypeInSwaggerSchema + { + get + { return ResourceManager.GetString("InvalidTypeInSwaggerSchema", resourceCulture); } } - + /// /// Looks up a localized string similar to Since operation '{0}' response has model definition '{1}', it should be of the form "*_list*". Note: If you have already shipped an SDK on top of this spec, fixing this warning may introduce a breaking change.. /// - internal static string ListOperationsNamingWarningMessage { - get { + internal static string ListOperationsNamingWarningMessage + { + get + { return ResourceManager.GetString("ListOperationsNamingWarningMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to The operation '{0}' returns 202 status code, which indicates a long running operation, please enable "x-ms-long-running-operation.. /// - internal static string LongRunningOperationsWithLongRunningExtension { - get { + internal static string LongRunningOperationsWithLongRunningExtension + { + get + { return ResourceManager.GetString("LongRunningOperationsWithLongRunningExtension", resourceCulture); } } - + /// /// Looks up a localized string similar to A '{0}' operation '{1}' with x-ms-long-running-operation extension must have a valid terminal success status code {2}.. /// - internal static string LongRunningResponseNotValid { - get { + internal static string LongRunningResponseNotValid + { + get + { return ResourceManager.GetString("LongRunningResponseNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to {0} lacks 'description' property. Consider adding a 'description' element. Accurate description is essential for maintaining reference documentation.. /// - internal static string MissingDescription { - get { + internal static string MissingDescription + { + get + { return ResourceManager.GetString("MissingDescription", resourceCulture); } } - + /// /// Looks up a localized string similar to {0} lacks 'description' and 'summary' property. Consider adding a 'description'/'summary' element. Accurate description/summary is essential for maintaining reference documentation.. /// - internal static string MissingSummaryDescription { - get { + internal static string MissingSummaryDescription + { + get + { return ResourceManager.GetString("MissingSummaryDescription", resourceCulture); } } - + /// /// Looks up a localized string similar to {0} lacks 'description' and 'title' property. Consider adding a 'description'/'title' element. Accurate description/title is essential for maintaining reference documentation.. /// - internal static string MissingTitleDescription { - get { + internal static string MissingTitleDescription + { + get + { return ResourceManager.GetString("MissingTitleDescription", resourceCulture); } } - + /// /// Looks up a localized string similar to Successfully initialized modeler {0} v {1}.. /// - internal static string ModelerInitialized { - get { + internal static string ModelerInitialized + { + get + { return ResourceManager.GetString("ModelerInitialized", resourceCulture); } } - + /// /// Looks up a localized string similar to For better generated code quality, remove all references to "msdn.microsoft.com".. /// - internal static string MsdnReferencesDiscouraged { - get { + internal static string MsdnReferencesDiscouraged + { + get + { return ResourceManager.GetString("MsdnReferencesDiscouraged", resourceCulture); } } - + /// /// Looks up a localized string similar to Collection format "multi" is only supported for Query parameters (parameter '{0}').. /// - internal static string MultiCollectionFormatNotSupported { - get { + internal static string MultiCollectionFormatNotSupported + { + get + { return ResourceManager.GetString("MultiCollectionFormatNotSupported", resourceCulture); } } - + /// /// Looks up a localized string similar to Only 'application/json' content-type is supported by ARM.. /// - internal static string NonAppJsonTypeNotSupported { - get { + internal static string NonAppJsonTypeNotSupported + { + get + { return ResourceManager.GetString("NonAppJsonTypeNotSupported", resourceCulture); } } - + /// /// Looks up a localized string similar to Method '{0}' does not declare any MIME type for the return body. Generated code will not deserialize the content.. /// - internal static string NoProduceOperationWithBody { - get { + internal static string NoProduceOperationWithBody + { + get + { return ResourceManager.GetString("NoProduceOperationWithBody", resourceCulture); } } - + /// /// Looks up a localized string similar to Only 1 underscore is permitted in the operation id, following Noun_Verb conventions.. /// - internal static string OnlyOneUnderscoreAllowedInOperationId { - get { + internal static string OnlyOneUnderscoreAllowedInOperationId + { + get + { return ResourceManager.GetString("OnlyOneUnderscoreAllowedInOperationId", resourceCulture); } } - + /// /// Looks up a localized string similar to OperationId is required for all operations. Please add it for '{0}' operation of '{1}' path.. /// - internal static string OperationIdMissing { - get { + internal static string OperationIdMissing + { + get + { return ResourceManager.GetString("OperationIdMissing", resourceCulture); } } - + /// /// Looks up a localized string similar to OperationId has a noun that conflicts with one of the model names in definitions section. The model name will be disambiguated to '{0}Model'. Consider using the plural form of '{1}' to avoid this. Note: If you have already shipped an SDK on top of this spec, fixing this warning may introduce a breaking change.. /// - internal static string OperationIdNounConflictingModelNamesMessage { - get { + internal static string OperationIdNounConflictingModelNamesMessage + { + get + { return ResourceManager.GetString("OperationIdNounConflictingModelNamesMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to Per the Noun_Verb convention for Operation Ids, the noun '{0}' should not appear after the underscore. Note: If you have already shipped an SDK on top of this spec, fixing this warning may introduce a breaking change.. /// - internal static string OperationIdNounInVerb { - get { + internal static string OperationIdNounInVerb + { + get + { return ResourceManager.GetString("OperationIdNounInVerb", resourceCulture); } } - + /// /// Looks up a localized string similar to Parameter "subscriptionId" is not allowed in the operations section, define it in the global parameters section instead. /// - internal static string OperationParametersNotAllowedMessage { - get { + internal static string OperationParametersNotAllowedMessage + { + get + { return ResourceManager.GetString("OperationParametersNotAllowedMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to Operations API must be implemented for '{0}'.. /// - internal static string OperationsAPINotImplemented { - get { + internal static string OperationsAPINotImplemented + { + get + { return ResourceManager.GetString("OperationsAPINotImplemented", resourceCulture); } } - + /// /// Looks up a localized string similar to Options HTTP verb is not supported.. /// - internal static string OptionsNotSupported { - get { + internal static string OptionsNotSupported + { + get + { return ResourceManager.GetString("OptionsNotSupported", resourceCulture); } } - + /// /// Looks up a localized string similar to Parameter Must have the "name" property defined with non-empty string as its value. /// - internal static string ParametersPropertiesValidation { - get { + internal static string ParametersPropertiesValidation + { + get + { return ResourceManager.GetString("ParametersPropertiesValidation", resourceCulture); } } - + /// /// Looks up a localized string similar to Parsing swagger json file.. /// - internal static string ParsingSwagger { - get { + internal static string ParsingSwagger + { + get + { return ResourceManager.GetString("ParsingSwagger", resourceCulture); } } - + /// /// Looks up a localized string similar to 'PATCH' operation '{0}' should use method name 'Update'. Note: If you have already shipped an SDK on top of this spec, fixing this warning may introduce a breaking change.. /// - internal static string PatchOperationNameNotValid { - get { + internal static string PatchOperationNameNotValid + { + get + { return ResourceManager.GetString("PatchOperationNameNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to {0} has different responses for PUT/GET/PATCH operations. The PUT/GET/PATCH operations must have same schema response.. /// - internal static string PutGetPatchResponseInvalid { - get { + internal static string PutGetPatchResponseInvalid + { + get + { return ResourceManager.GetString("PutGetPatchResponseInvalid", resourceCulture); } } - + /// /// Looks up a localized string similar to 'PUT' operation '{0}' should use method name 'Create'. Note: If you have already shipped an SDK on top of this spec, fixing this warning may introduce a breaking change.. /// - internal static string PutOperationNameNotValid { - get { + internal static string PutOperationNameNotValid + { + get + { return ResourceManager.GetString("PutOperationNameNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to A PUT operation request body schema should be the same as its 200 response schema, to allow reusing the same entity between GET and PUT. If the schema of the PUT request body is a superset of the GET response body, make sure you have a PATCH operation to make the resource updatable. Operation: '{0}' Request Model: '{1}' Response Model: '{2}'. /// - internal static string PutOperationRequestResponseSchemaMessage { - get { + internal static string PutOperationRequestResponseSchemaMessage + { + get + { return ResourceManager.GetString("PutOperationRequestResponseSchemaMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to The 200 response model for an ARM PUT operation must have x-ms-azure-resource extension set to true in its hierarchy. Operation: '{0}' Model: '{1}'.. /// - internal static string PutOperationResourceResponseValidationMessage { - get { + internal static string PutOperationResourceResponseValidationMessage + { + get + { return ResourceManager.GetString("PutOperationResourceResponseValidationMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to Property '{0}' in Model '{1}' is marked readOnly and is also required. This is not allowed.. /// - internal static string ReadOnlyNotRequired { - get { + internal static string ReadOnlyNotRequired + { + get + { return ResourceManager.GetString("ReadOnlyNotRequired", resourceCulture); } } - + /// /// Looks up a localized string similar to Reference path '{0}' does not exist in the definition section of the Swagger document.. /// - internal static string ReferenceDoesNotExist { - get { + internal static string ReferenceDoesNotExist + { + get + { return ResourceManager.GetString("ReferenceDoesNotExist", resourceCulture); } } - + /// /// Looks up a localized string similar to Property '{0}' is a required property. It should not be marked as 'readonly'.. /// - internal static string RequiredReadOnlyPropertiesValidation { - get { + internal static string RequiredReadOnlyPropertiesValidation + { + get + { return ResourceManager.GetString("RequiredReadOnlyPropertiesValidation", resourceCulture); } } - + /// /// Looks up a localized string similar to A 'Resource' definition must have x-ms-azure-resource extension enabled and set to true.. /// - internal static string ResourceIsMsResourceNotValid { - get { + internal static string ResourceIsMsResourceNotValid + { + get + { return ResourceManager.GetString("ResourceIsMsResourceNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to Model definition '{0}' must have the properties 'name', 'id' and 'type' in its hierarchy and these properties must be marked as readonly.. /// - internal static string ResourceModelIsNotValid { - get { + internal static string ResourceModelIsNotValid + { + get + { return ResourceManager.GetString("ResourceModelIsNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to Every swagger/configuration must have a security definitions section and it must adhere to the structure described in: https://github.com/Azure/autorest/tree/master/docs/developer/validation-rules/security-definitions-structure-validation.md. /// - internal static string SecurityDefinitionsStructureValidation { - get { + internal static string SecurityDefinitionsStructureValidation + { + get + { return ResourceManager.GetString("SecurityDefinitionsStructureValidation", resourceCulture); } } - + /// /// Looks up a localized string similar to Parameter "{0}" is referenced but not defined in the global parameters section of Service Definition. /// - internal static string ServiceDefinitionParametersMissingMessage { - get { + internal static string ServiceDefinitionParametersMissingMessage + { + get + { return ResourceManager.GetString("ServiceDefinitionParametersMissingMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to Sku Model definition '{0}' is not valid. A Sku model must have 'name' property. It can also have 'tier', 'size', 'family', 'capacity' as optional properties.. /// - internal static string SkuModelIsNotValid { - get { + internal static string SkuModelIsNotValid + { + get + { return ResourceManager.GetString("SkuModelIsNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to The summary and description values should not be same.. /// - internal static string SummaryDescriptionVaidationError { - get { + internal static string SummaryDescriptionVaidationError + { + get + { return ResourceManager.GetString("SummaryDescriptionVaidationError", resourceCulture); } } - + /// /// Looks up a localized string similar to Azure Resource Management only supports HTTPS scheme.. /// - internal static string SupportedSchemesWarningMessage { - get { + internal static string SupportedSchemesWarningMessage + { + get + { return ResourceManager.GetString("SupportedSchemesWarningMessage", resourceCulture); } } - + /// /// Looks up a localized string similar to Swagger specification is missing title in info section. /// - internal static string TitleMissing { - get { + internal static string TitleMissing + { + get + { return ResourceManager.GetString("TitleMissing", resourceCulture); } } - + /// /// Looks up a localized string similar to Tracked resource '{0}' must have a get operation.. /// - internal static string TrackedResourceGetOperationMissing { - get { + internal static string TrackedResourceGetOperationMissing + { + get + { return ResourceManager.GetString("TrackedResourceGetOperationMissing", resourceCulture); } } - + /// /// Looks up a localized string similar to The child tracked resource, '{0}' with immediate parent '{1}', must have a list by immediate parent operation.. /// - internal static string TrackedResourceListByImmediateParentOperationMissing { - get { + internal static string TrackedResourceListByImmediateParentOperationMissing + { + get + { return ResourceManager.GetString("TrackedResourceListByImmediateParentOperationMissing", resourceCulture); } } - + /// /// Looks up a localized string similar to The tracked resource, '{0}', must have a list by resource group operation.(This rule does not apply for tenant level resources.). /// - internal static string TrackedResourceListByResourceGroupOperationMissing { - get { + internal static string TrackedResourceListByResourceGroupOperationMissing + { + get + { return ResourceManager.GetString("TrackedResourceListByResourceGroupOperationMissing", resourceCulture); } } - + /// /// Looks up a localized string similar to The tracked resource, '{0}', must have a list by subscriptions operation.. /// - internal static string TrackedResourceListBySubscriptionsOperationMissing { - get { + internal static string TrackedResourceListBySubscriptionsOperationMissing + { + get + { return ResourceManager.GetString("TrackedResourceListBySubscriptionsOperationMissing", resourceCulture); } } - + /// /// Looks up a localized string similar to Tracked resource '{0}' must have patch operation that at least supports the update of tags. It's strongly recommended that the PATCH operation supports update of all mutable properties as well.. /// - internal static string TrackedResourcePatchOperationMissing { - get { + internal static string TrackedResourcePatchOperationMissing + { + get + { return ResourceManager.GetString("TrackedResourcePatchOperationMissing", resourceCulture); } } - + /// /// Looks up a localized string similar to Multiple resource providers are not allowed in a single spec. More than one the resource paths were found: '{0}'.. /// - internal static string UniqueResourcePaths { - get { + internal static string UniqueResourcePaths + { + get + { return ResourceManager.GetString("UniqueResourcePaths", resourceCulture); } } - + /// /// Looks up a localized string similar to '{0}' is not a known format.. /// - internal static string UnknownFormat { - get { + internal static string UnknownFormat + { + get + { return ResourceManager.GetString("UnknownFormat", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid swagger 2.0 specification. Missing version property. . /// - internal static string UnknownSwaggerVersion { - get { + internal static string UnknownSwaggerVersion + { + get + { return ResourceManager.GetString("UnknownSwaggerVersion", resourceCulture); } } - + /// /// Looks up a localized string similar to The operation '{0}' has a response body in response '{1}', but did not have a supported MIME type ('application/json' or 'application/octet-stream') in its Produces property.. /// - internal static string UnsupportedMimeTypeForResponseBody { - get { + internal static string UnsupportedMimeTypeForResponseBody + { + get + { return ResourceManager.GetString("UnsupportedMimeTypeForResponseBody", resourceCulture); } } - + /// /// Looks up a localized string similar to Value of 'x-ms-client-name' cannot be the same as '{0}' Property/Model.. /// - internal static string XmsClientNameInvalid { - get { + internal static string XmsClientNameInvalid + { + get + { return ResourceManager.GetString("XmsClientNameInvalid", resourceCulture); } } - + /// /// Looks up a localized string similar to For the tracked resource '{0}', the x-ms-pageable extension values must be same for list by resource group and subscriptions operations.. /// - internal static string XMSPagableListByRGAndSubscriptionsMismatch { - get { + internal static string XMSPagableListByRGAndSubscriptionsMismatch + { + get + { return ResourceManager.GetString("XMSPagableListByRGAndSubscriptionsMismatch", resourceCulture); } } - + /// /// Looks up a localized string similar to Paths in x-ms-paths must overload a normal path in the paths section, i.e. a path in the x-ms-paths must either be same as a path in the paths section or a path in the paths sections followed by additional parameters.. /// - internal static string XMSPathBaseNotInPaths { - get { + internal static string XMSPathBaseNotInPaths + { + get + { return ResourceManager.GetString("XMSPathBaseNotInPaths", resourceCulture); } } + + /// + /// Looks up a localized string similar to The parameter '{0}' is defined in global parameters section without 'x-ms-parameter-location' extension. This would add the parameter as the client property. Please ensure that this is exactly you want. If so, apply the extension "x-ms-parameter-location": "client". Else, apply the extension "x-ms-parameter-location": "method". + /// + internal static string XmsParameterLocation + { + get + { + return ResourceManager.GetString("XmsParameterLocation", resourceCulture); + } + } } } diff --git a/src/dotnet/OpenAPI.Validator/Properties/Resources.resx b/src/dotnet/OpenAPI.Validator/Properties/Resources.resx index 68e5033f9..77d6f84d6 100644 --- a/src/dotnet/OpenAPI.Validator/Properties/Resources.resx +++ b/src/dotnet/OpenAPI.Validator/Properties/Resources.resx @@ -357,4 +357,7 @@ The operation '{0}' returns 202 status code, which indicates a long running operation, please enable "x-ms-long-running-operation. + + The parameter '{0}' is defined in global parameters section without 'x-ms-parameter-location' extension. This would add the parameter as the client property. Please ensure that this is exactly you want. If so, apply the extension "x-ms-parameter-location": "client". Else, apply the extension "x-ms-parameter-location": "method". + diff --git a/src/dotnet/OpenAPI.Validator/Validation/XmsParameterLocation.cs b/src/dotnet/OpenAPI.Validator/Validation/XmsParameterLocation.cs new file mode 100644 index 000000000..20e7f89f9 --- /dev/null +++ b/src/dotnet/OpenAPI.Validator/Validation/XmsParameterLocation.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using AutoRest.Core.Logging; +using OpenAPI.Validator.Properties; +using OpenAPI.Validator.Validation.Core; +using OpenAPI.Validator.Model; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAPI.Validator.Validation +{ + public class XmsParameterLocation : TypedRule + { + private static readonly IEnumerable AllowedGlobalParameters = new List() + { "subscriptionid", "api-version", "apiversion", "subscription-id" }; + + /// + /// Id of the Rule. + /// + public override string Id => "R4001"; + + /// + /// Violation category of the Rule. + /// + public override ValidationCategory ValidationCategory => ValidationCategory.SDKViolation; + + /// + /// The template message for this Rule. + /// + /// + /// This may contain placeholders '{0}' for parameterized messages. + /// + public override string MessageTemplate => Resources.XmsParameterLocation; + + /// + /// The severity of this message (ie, debug/info/warning/error/fatal, etc) + /// + public override Category Severity => Category.Error; + + /// + /// What kind of open api document type this rule should be applied to + /// + public override ServiceDefinitionDocumentType ServiceDefinitionDocumentType => ServiceDefinitionDocumentType.ARM | ServiceDefinitionDocumentType.DataPlane; + + /// + /// What state of the document to run the validation rule on + /// + public override ServiceDefinitionDocumentState ValidationRuleMergeState => ServiceDefinitionDocumentState.Individual; + + public override IEnumerable GetValidationMessages(SwaggerParameter parameter, RuleContext context) + { + if (!AllowedGlobalParameters.Contains(parameter.Name.ToLower()) && + parameter.Extensions?.Keys?.Contains("x-ms-parameter-location") == false) + { + yield return new ValidationMessage(new FileObjectPath(context.File, context.Path), this, parameter.Name); + } + } + } +}