feat(go_indexer): add deprecation facts for go (#3692)

diff --git a/kythe/go/indexer/BUILD b/kythe/go/indexer/BUILD
index a605370..3a4b0fa 100644
--- a/kythe/go/indexer/BUILD
+++ b/kythe/go/indexer/BUILD
@@ -49,6 +49,11 @@
 )
 
 go_indexer_test(
+    name = "deprecation_test",
+    srcs = ["testdata/basic/deprecation.go"],
+)
+
+go_indexer_test(
     name = "filenode_test",
     srcs = ["testdata/basic/filenode.go"],
     import_path = "test/basic",
diff --git a/kythe/go/indexer/emit.go b/kythe/go/indexer/emit.go
index 5b77624..8cd78b8 100644
--- a/kythe/go/indexer/emit.go
+++ b/kythe/go/indexer/emit.go
@@ -970,6 +970,7 @@
 func (e *emitter) writeDef(node ast.Node, target *spb.VName) { e.writeRef(node, target, edges.Defines) }
 
 // writeDoc adds associations between comment groups and a documented node.
+// It also handles marking deprecated facts on the target.
 func (e *emitter) writeDoc(comments *ast.CommentGroup, target *spb.VName) {
 	if comments == nil || len(comments.List) == 0 || target == nil {
 		return
@@ -981,8 +982,29 @@
 	docNode := proto.Clone(target).(*spb.VName)
 	docNode.Signature += " doc"
 	e.writeFact(docNode, facts.NodeKind, nodes.Doc)
-	e.writeFact(docNode, facts.Text, strings.Join(lines, "\n"))
+	e.writeFact(docNode, facts.Text, escComment.Replace(strings.Join(lines, "\n")))
 	e.writeEdge(docNode, target, edges.Documents)
+	e.emitDeprecation(target, lines)
+}
+
+// emitDeprecation emits a deprecated fact for the specified target if the
+// comment lines indicate it is deprecated per https://github.com/golang/go/wiki/Deprecated
+func (e *emitter) emitDeprecation(target *spb.VName, lines []string) {
+	var deplines []string
+	for _, line := range lines {
+		if len(deplines) == 0 {
+			if msg := strings.TrimPrefix(line, "Deprecated:"); msg != line {
+				deplines = append(deplines, strings.TrimSpace(msg))
+			}
+		} else if line == "" {
+			break
+		} else {
+			deplines = append(deplines, strings.TrimSpace(line))
+		}
+	}
+	if len(deplines) > 0 {
+		e.writeFact(target, facts.Deprecated, strings.Join(deplines, " "))
+	}
 }
 
 // isCall reports whether id is a call to obj.  This holds if id is in call
@@ -1159,14 +1181,12 @@
 
 // trimComment removes the comment delimiters from a comment.  For single-line
 // comments, it also removes a single leading space, if present; for multi-line
-// comments it discards leading and trailing whitespace. Brackets and backslash
-// characters are escaped per http://www.kythe.io/docs/schema/#doc.
+// comments it discards leading and trailing whitespace.
 func trimComment(text string) string {
 	if single := strings.TrimPrefix(text, "//"); single != text {
-		return escComment.Replace(strings.TrimPrefix(single, " "))
+		return strings.TrimPrefix(single, " ")
 	}
-	trimmed := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(text, "/*"), "*/"))
-	return escComment.Replace(trimmed)
+	return strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(text, "/*"), "*/"))
 }
 
 // specComment returns the innermost comment associated with spec, or nil.
diff --git a/kythe/go/indexer/testdata/basic/deprecation.go b/kythe/go/indexer/testdata/basic/deprecation.go
new file mode 100644
index 0000000..4e691ae
--- /dev/null
+++ b/kythe/go/indexer/testdata/basic/deprecation.go
@@ -0,0 +1,50 @@
+// Package deprecate tests deprecation.
+
+//- @+3dep defines/binding Pkg
+
+// Deprecated: dep should not be used
+package dep
+
+//- Pkg.node/kind package
+//- Pkg.tag/deprecated "dep should not be used"
+
+//- @+6topLevel defines/binding TopLevel
+//- TopLevel.node/kind variable
+//- TopLevel.tag/deprecated "topLevel has insufficient precision"
+//- TopLevel childof Pkg
+
+// Deprecated: topLevel has insufficient precision
+var topLevel int
+
+//- @+4outer defines/binding Outer
+//- Outer.tag/deprecated "outer has been replaced by inner"
+
+// Deprecated: outer has been replaced by inner
+func outer() {
+	//- @+6stabby defines/binding V
+	//- V.node/kind variable
+	//- V childof Outer
+	//- V.tag/deprecated "stabby is too sharp"
+
+	// Deprecated: stabby is too sharp
+	var stabby bool
+
+	_ = stabby // suppress unused variable error
+}
+
+//- @+6multilineDep defines/binding Func
+//- Func.tag/deprecated "more than one line for deprecation message"
+
+// Deprecated: more than one
+// line for deprecation
+// message
+func multilineDep() {
+}
+
+//- @+6magic defines/binding Const
+//- Const.node/kind constant
+//- Const.tag/deprecated "use technology instead"
+//- Const childof Pkg
+
+// Deprecated: use technology instead
+const magic = "beans"
diff --git a/kythe/go/util/schema/facts/facts.go b/kythe/go/util/schema/facts/facts.go
index 53feddb..d95752c 100644
--- a/kythe/go/util/schema/facts/facts.go
+++ b/kythe/go/util/schema/facts/facts.go
@@ -27,6 +27,7 @@
 	Code         = prefix + "code"
 	Complete     = prefix + "complete"
 	ContextURL   = prefix + "context/url"
+	Deprecated   = prefix + "tag/deprecated"
 	Details      = prefix + "details"
 	DocURI       = prefix + "doc/uri"
 	Message      = prefix + "message"