internal/report: refactor - add Description type

Add named type Description for Report descriptions, and move logic
to lint descriptions to method Description.lint.

Change-Id: Ie198b7c9ec89fe3dc64676e033d8ebe12145b3ea

squash description

Change-Id: I92d376181f4472010024c3ffaf0ef597b7ad1ac0
Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/542357
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/cmd/vulnreport/main.go b/cmd/vulnreport/main.go
index c6ad84b..5319885 100644
--- a/cmd/vulnreport/main.go
+++ b/cmd/vulnreport/main.go
@@ -719,7 +719,7 @@
 	if any(r.CVEs) || any(r.GHSAs) {
 		return true
 	}
-	return is(r.Summary.String()) || is(r.Description) || any(r.Credits)
+	return is(r.Summary.String()) || is(r.Description.String()) || any(r.Credits)
 }
 
 // addReferenceTODOs adds a TODO for each important reference type not
diff --git a/cmd/vulnreport/suggest.go b/cmd/vulnreport/suggest.go
index 5dc7895..54be40b 100644
--- a/cmd/vulnreport/suggest.go
+++ b/cmd/vulnreport/suggest.go
@@ -31,7 +31,7 @@
 
 	suggestions, err := c.Suggest(&palmapi.Input{
 		Module:      r.Modules[0].Module,
-		Description: r.Description,
+		Description: r.Description.String(),
 	})
 	if err != nil {
 		return fmt.Errorf("PaLM API error: %s", err)
@@ -67,7 +67,7 @@
 			switch choice {
 			case "a":
 				r.Summary = report.Summary(s.Summary)
-				r.Description = s.Description
+				r.Description = report.Description(s.Description)
 				if err := r.Write(filename); err != nil {
 					errlog.Println(err)
 				}
diff --git a/internal/genericosv/report.go b/internal/genericosv/report.go
index 12a1aef..9ca8269 100644
--- a/internal/genericosv/report.go
+++ b/internal/genericosv/report.go
@@ -27,7 +27,7 @@
 	r := &report.Report{
 		ID:          goID,
 		Summary:     report.Summary(osv.Summary),
-		Description: osv.Details,
+		Description: report.Description(osv.Details),
 	}
 	addAlias := func(alias string) {
 		switch {
diff --git a/internal/palmapi/gen_examples/main.go b/internal/palmapi/gen_examples/main.go
index cb53679..4fce1c8 100644
--- a/internal/palmapi/gen_examples/main.go
+++ b/internal/palmapi/gen_examples/main.go
@@ -133,7 +133,7 @@
 			},
 			Suggestion: palmapi.Suggestion{
 				Summary:     removeNewlines(v.r.Summary.String()),
-				Description: removeNewlines(v.r.Description),
+				Description: removeNewlines(v.r.Description.String()),
 			},
 		}
 		es = append(es, ex)
diff --git a/internal/report/cve.go b/internal/report/cve.go
index 303b7fb..032ade6 100644
--- a/internal/report/cve.go
+++ b/internal/report/cve.go
@@ -33,9 +33,9 @@
 
 // CVEToReport creates a Report struct from a given CVE and modulePath.
 func CVEToReport(c *cveschema.CVE, modulePath string, pc *proxy.Client) *Report {
-	var description string
+	var description Description
 	for _, d := range c.Description.Data {
-		description += d.Value + "\n"
+		description += Description(d.Value + "\n")
 	}
 	var refs []*Reference
 	for _, r := range c.References.Data {
diff --git a/internal/report/cve5.go b/internal/report/cve5.go
index fa36095..28fa5cb 100644
--- a/internal/report/cve5.go
+++ b/internal/report/cve5.go
@@ -35,7 +35,7 @@
 	}
 	description := r.CVEMetadata.Description
 	if description == "" {
-		description = r.Description
+		description = r.Description.String()
 	}
 	if r.CVEMetadata.CWE == "" {
 		return nil, errors.New("report missing CWE")
diff --git a/internal/report/fix.go b/internal/report/fix.go
index 86de67c..18fe88f 100644
--- a/internal/report/fix.go
+++ b/internal/report/fix.go
@@ -27,7 +27,7 @@
 		*sp = fixLineLength(*sp, maxLineLength)
 	}
 	fixLines((*string)(&r.Summary))
-	fixLines(&r.Description)
+	fixLines((*string)(&r.Description))
 	if r.CVEMetadata != nil {
 		fixLines(&r.CVEMetadata.Description)
 	}
diff --git a/internal/report/ghsa.go b/internal/report/ghsa.go
index c489ec9..23b7cc3 100644
--- a/internal/report/ghsa.go
+++ b/internal/report/ghsa.go
@@ -16,7 +16,7 @@
 func GHSAToReport(sa *ghsa.SecurityAdvisory, modulePath string, pc *proxy.Client) *Report {
 	r := &Report{
 		Summary:     Summary(sa.Summary),
-		Description: sa.Description,
+		Description: Description(sa.Description),
 	}
 	var cves, ghsas []string
 	for _, id := range sa.Identifiers {
diff --git a/internal/report/lint.go b/internal/report/lint.go
index ee05761..8efd311 100644
--- a/internal/report/lint.go
+++ b/internal/report/lint.go
@@ -277,8 +277,9 @@
 	}
 }
 
-func (r *Report) lintDescription(addIssue func(string)) {
-	if r.Description == "" && r.CVEMetadata != nil {
+func (d *Description) lint(addIssue func(string), r *Report) {
+	desc := d.String()
+	if desc == "" && r.CVEMetadata != nil {
 		addIssue("missing description (reports with Go CVEs must have a description)")
 	}
 	hasAdvisory := func() bool {
@@ -289,7 +290,7 @@
 		}
 		return false
 	}
-	if r.Description == "" && r.CVEMetadata == nil && !hasAdvisory() {
+	if desc == "" && r.CVEMetadata == nil && !hasAdvisory() {
 		addIssue("missing advisory (reports without descriptions must have an advisory link)")
 	}
 }
@@ -407,7 +408,7 @@
 		if len(r.Modules) == 0 {
 			addIssue("no modules")
 		}
-		r.lintDescription(addIssue)
+		r.Description.lint(addIssue, r)
 		r.Summary.lint(addIssue)
 	}
 
@@ -446,7 +447,7 @@
 		m.lintVersions(addPkgIssue)
 	}
 
-	r.lintLineLength("description", r.Description, addIssue)
+	r.lintLineLength("description", r.Description.String(), addIssue)
 	if r.CVEMetadata != nil {
 		r.lintLineLength("cve_metadata.description", r.CVEMetadata.Description, addIssue)
 	}
diff --git a/internal/report/osv.go b/internal/report/osv.go
index 54f83a1..477865e 100644
--- a/internal/report/osv.go
+++ b/internal/report/osv.go
@@ -50,7 +50,7 @@
 	// govulncheck can robustly display summaries in place of details.
 	details := r.Description
 	if details == "" {
-		details = r.Summary.String()
+		details = Description(r.Summary)
 	}
 
 	entry := osv.Entry{
@@ -60,7 +60,7 @@
 		Withdrawn:        withdrawn,
 		Related:          r.Related,
 		Summary:          toParagraphs(r.Summary.String()),
-		Details:          toParagraphs(details),
+		Details:          toParagraphs(details.String()),
 		Credits:          credits,
 		SchemaVersion:    SchemaVersion,
 		DatabaseSpecific: &osv.DatabaseSpecific{URL: GoAdvisory(r.ID)},
diff --git a/internal/report/report.go b/internal/report/report.go
index cd9f389..84692e0 100644
--- a/internal/report/report.go
+++ b/internal/report/report.go
@@ -193,9 +193,9 @@
 
 	// Description is the CVE description from an existing CVE. If we are
 	// assigning a CVE ID ourselves, use CVEMetadata.Description instead.
-	Description string     `yaml:",omitempty"`
-	Published   time.Time  `yaml:",omitempty"`
-	Withdrawn   *time.Time `yaml:",omitempty"`
+	Description Description `yaml:",omitempty"`
+	Published   time.Time   `yaml:",omitempty"`
+	Withdrawn   *time.Time  `yaml:",omitempty"`
 
 	// CVE are CVE IDs for existing CVEs.
 	// If we are assigning a CVE ID ourselves, use CVEMetadata.ID instead.
@@ -224,11 +224,16 @@
 }
 
 type Summary string
+type Description string
 
 func (s *Summary) String() string {
 	return string(*s)
 }
 
+func (d *Description) String() string {
+	return string(*d)
+}
+
 // GoCVE returns the CVE assigned to this report by the Go CNA,
 // or the empty string if not applicable.
 func (r *Report) GoCVE() string {