modfile: make marking for removal a method on Line instead of FileSyntax

The act of marking a line for removal intentionally does not depend on
the rest of the syntax tree, in order to avoid quadratic behavior.
Make that property more explicit by defining it as a method on Line
rather than FileSyntax.

For golang/go#45965

Change-Id: I475625eddf57396411a3fb73eaedd624dd7af3d6
Reviewed-on: https://go-review.googlesource.com/c/mod/+/325969
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
diff --git a/modfile/read.go b/modfile/read.go
index 81e7609..956f30c 100644
--- a/modfile/read.go
+++ b/modfile/read.go
@@ -194,13 +194,15 @@
 	line.Token = tokens
 }
 
-func (x *FileSyntax) removeLine(line *Line) {
+// markRemoved modifies line so that it (and its end-of-line comment, if any)
+// will be dropped by (*FileSyntax).Cleanup.
+func (line *Line) markRemoved() {
 	line.Token = nil
 	line.Comments.Suffix = nil
 }
 
 // Cleanup cleans up the file syntax x after any edit operations.
-// To avoid quadratic behavior, removeLine marks the line as dead
+// To avoid quadratic behavior, (*Line).markRemoved marks the line as dead
 // by setting line.Token = nil but does not remove it from the slice
 // in which it appears. After edits have all been indicated,
 // calling Cleanup cleans out the dead lines.
diff --git a/modfile/rule.go b/modfile/rule.go
index 71cda84..f1776c4 100644
--- a/modfile/rule.go
+++ b/modfile/rule.go
@@ -850,7 +850,7 @@
 				f.Syntax.updateLine(r.Syntax, "require", AutoQuote(path), vers)
 				need = false
 			} else {
-				f.Syntax.removeLine(r.Syntax)
+				r.Syntax.markRemoved()
 				*r = Require{}
 			}
 		}
@@ -902,7 +902,7 @@
 		if !ok {
 			// This line is redundant or its path is no longer required at all.
 			// Mark the requirement for deletion in Cleanup.
-			r.Syntax.Token = nil
+			r.Syntax.markRemoved()
 			*r = Require{}
 		}
 
@@ -946,7 +946,7 @@
 func (f *File) DropRequire(path string) error {
 	for _, r := range f.Require {
 		if r.Mod.Path == path {
-			f.Syntax.removeLine(r.Syntax)
+			r.Syntax.markRemoved()
 			*r = Require{}
 		}
 	}
@@ -977,7 +977,7 @@
 func (f *File) DropExclude(path, vers string) error {
 	for _, x := range f.Exclude {
 		if x.Mod.Path == path && x.Mod.Version == vers {
-			f.Syntax.removeLine(x.Syntax)
+			x.Syntax.markRemoved()
 			*x = Exclude{}
 		}
 	}
@@ -1008,7 +1008,7 @@
 				continue
 			}
 			// Already added; delete other replacements for same.
-			f.Syntax.removeLine(r.Syntax)
+			r.Syntax.markRemoved()
 			*r = Replace{}
 		}
 		if r.Old.Path == oldPath {
@@ -1024,7 +1024,7 @@
 func (f *File) DropReplace(oldPath, oldVers string) error {
 	for _, r := range f.Replace {
 		if r.Old.Path == oldPath && r.Old.Version == oldVers {
-			f.Syntax.removeLine(r.Syntax)
+			r.Syntax.markRemoved()
 			*r = Replace{}
 		}
 	}
@@ -1065,7 +1065,7 @@
 func (f *File) DropRetract(vi VersionInterval) error {
 	for _, r := range f.Retract {
 		if r.VersionInterval == vi {
-			f.Syntax.removeLine(r.Syntax)
+			r.Syntax.markRemoved()
 			*r = Retract{}
 		}
 	}