Repository: oapi-codegen/oapi-codegen (Go)

Issue:
Generate proper comments for deprecated fields
The OpenAPI 3 spec specifies a field to flag a property as deprecated. oapi-codegen does not process this field, even though there is a standard way of marking fields (and other things) as deprecated in Go: https://github.com/golang/go/wiki/Deprecated

It should also be possible to add an extension comment to explain why something is deprecated and what to use instead.

Example YAML:
```yaml
components:
  schemas:
    DeprecatedProperty:
      type: object
      required:
        - newProp
        - oldProp
      properties:
        newProp:
          type: string
          description: Use this now!
        oldProp1:
          type: string
          deprecated: true
          # description: No description on this one to test generation in that case
        oldProp2:
          type: string
          deprecated: true
          description: It used to do this and that
        oldProp3:
          type: string
          deprecated: true
          x-deprecated-reason: Use NewProp instead!
        oldProp4:
          type: string
          deprecated: true
          x-deprecated-reason: Use NewProp instead!
          description: It used to do this and that
```

Expected Go code:
```go
// DeprecatedProperty defines model for DeprecatedProperty.
type DeprecatedProperty struct {
	// NewProp Use this now!
	NewProp string `json:"newProp"`
	// Deprecated:
	OldProp1 *string `json:"oldProp1,omitempty"`

	// OldProp2 It used to do this and that
	// Deprecated:
	OldProp2 *string `json:"oldProp2,omitempty"`
	// Deprecated: Use NewProp instead!
	OldProp3 *string `json:"oldProp3,omitempty"`

	// OldProp4 It used to do this and that
	// Deprecated: Use NewProp instead!
	OldProp4 *string `json:"oldProp4,omitempty"`
}
```



Fix (patch):
diff --git a/pkg/codegen/extension.go b/pkg/codegen/extension.go
index 483d6d814..ca4c3b669 100644
--- a/pkg/codegen/extension.go
+++ b/pkg/codegen/extension.go
@@ -12,12 +12,13 @@ const (
 	// extGoName is used to override a field name
 	extGoName = "x-go-name"
 	// extGoTypeName is used to override a generated typename for something.
-	extGoTypeName       = "x-go-type-name"
-	extPropGoJsonIgnore = "x-go-json-ignore"
-	extPropOmitEmpty    = "x-omitempty"
-	extPropExtraTags    = "x-oapi-codegen-extra-tags"
-	extEnumVarNames     = "x-enum-varnames"
-	extEnumNames        = "x-enumNames"
+	extGoTypeName        = "x-go-type-name"
+	extPropGoJsonIgnore  = "x-go-json-ignore"
+	extPropOmitEmpty     = "x-omitempty"
+	extPropExtraTags     = "x-oapi-codegen-extra-tags"
+	extEnumVarNames      = "x-enum-varnames"
+	extEnumNames         = "x-enumNames"
+	extDeprecationReason = "x-deprecated-reason"
 )
 
 func extString(extPropValue interface{}) (string, error) {
@@ -82,3 +83,7 @@ func extParseEnumVarNames(extPropValue interface{}) ([]string, error) {
 	}
 	return names, nil
 }
+
+func extParseDeprecationReason(extPropValue interface{}) (string, error) {
+	return extString(extPropValue)
+}
diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go
index 1f10d4823..8fd990c5f 100644
--- a/pkg/codegen/schema.go
+++ b/pkg/codegen/schema.go
@@ -84,6 +84,7 @@ type Property struct {
 	WriteOnly     bool
 	NeedsFormTag  bool
 	Extensions    map[string]interface{}
+	Deprecated    bool
 }
 
 func (p Property) GoFieldName() string {
@@ -387,6 +388,7 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
 					ReadOnly:      p.Value.ReadOnly,
 					WriteOnly:     p.Value.WriteOnly,
 					Extensions:    p.Value.Extensions,
+					Deprecated:    p.Value.Deprecated,
 				}
 				outSchema.Properties = append(outSchema.Properties, prop)
 			}
@@ -621,6 +623,18 @@ func GenFieldsFromProperties(props []Property) []string {
 			field += fmt.Sprintf("%s\n", StringWithTypeNameToGoComment(p.Description, p.GoFieldName()))
 		}
 
+		if p.Deprecated {
+			// This comment has to be on its own line for godoc & IDEs to pick up
+			var deprecationReason string
+			if _, ok := p.Extensions[extDeprecationReason]; ok {
+				if extOmitEmpty, err := extParseDeprecationReason(p.Extensions[extDeprecationReason]); err == nil {
+					deprecationReason = extOmitEmpty
+				}
+			}
+
+			field += fmt.Sprintf("%s\n", DeprecationComment(deprecationReason))
+		}
+
 		field += fmt.Sprintf("    %s %s", goFieldName, p.GoTypeDef())
 
 		// Support x-omitempty
diff --git a/pkg/codegen/utils.go b/pkg/codegen/utils.go
index c5b0e60de..349bd7671 100644
--- a/pkg/codegen/utils.go
+++ b/pkg/codegen/utils.go
@@ -677,6 +677,15 @@ func StringWithTypeNameToGoComment(in, typeName string) string {
 	return stringToGoCommentWithPrefix(in, typeName)
 }
 
+func DeprecationComment(reason string) string {
+	var content = "Deprecated:" // The colon is required at the end even without reason
+	if reason != "" {
+		content += fmt.Sprintf(" %s", reason)
+	}
+
+	return stringToGoCommentWithPrefix(content, "")
+}
+
 func stringToGoCommentWithPrefix(in, prefix string) string {
 	if len(in) == 0 || len(strings.TrimSpace(in)) == 0 { // ignore empty comment
 		return ""