dmitri.shuralyov.com/go/generated/...

handle .go files with \r\n line endings

On Windows, a file that hasn't been gofmt'ed can have \r\n line endings.
Though rare and unusual, it's still a valid .go file and needs to be
supported.

The performance cost is not significant compared to the entire task.

	name         old time/op  new time/op  delta
	ParseFile-8  32.4µs ± 1%  32.4µs ± 1%   ~     (p=1.000 n=10+10)

Fixes https://github.com/shurcooL/go/issues/30.
dmitshur committed 4 years ago commit 8b6e764c43499f8595ac75086720dbe1624e0c02
generated.go
@@ -45,11 +45,15 @@ func Parse(src io.Reader) (hasGeneratedComment bool, err error) {
		if err == io.EOF {
			return containsComment(s), nil
		} else if err != nil {
			return false, err
		}
		s = s[:len(s)-1] // Trim newline.
		if len(s) >= 2 && s[len(s)-2] == '\r' {
			s = s[:len(s)-2] // Trim "\r\n".
		} else {
			s = s[:len(s)-1] // Trim "\n".
		}
		if containsComment(s) {
			return true, nil
		}
	}
}
generated_test.go
@@ -1,8 +1,10 @@
package generated_test

import (
	"bytes"
	"io/ioutil"
	"path/filepath"
	"testing"

	"dmitri.shuralyov.com/go/generated"
)
@@ -36,11 +38,33 @@ func TestParseFile(t *testing.T) {
	for _, tc := range tests {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			hasGeneratedComment, err := generated.ParseFile(filepath.Join("testdata", tc.name))
			if err != nil {
				t.Fatal(err)
				t.Error(err)
				return
			}
			if got, want := hasGeneratedComment, tc.want; got != want {
				t.Errorf("got hasGeneratedComment %v, want %v", got, want)
			}
		})

		// On Windows, a file that hasn't been gofmt'ed can have \r\n line endings.
		// Though rare and unusual, it's still a valid .go file and needs to be supported.
		t.Run(tc.name+` \r\n line ending version`, func(t *testing.T) {
			// Replace all "\n" line endings with "\r\n".
			b, err := ioutil.ReadFile(filepath.Join("testdata", tc.name))
			if err != nil {
				t.Error(err)
				return
			}
			b = bytes.Replace(b, []byte("\n"), []byte("\r\n"), -1)

			hasGeneratedComment, err := generated.Parse(bytes.NewReader(b))
			if err != nil {
				t.Error(err)
				return
			}
			if got, want := hasGeneratedComment, tc.want; got != want {
				t.Errorf("got hasGeneratedComment %v, want %v", got, want)
			}
		})