Repository: jhump/protoreflect (go)

Issue:
Regression upgrading from v1.14.1 to v1.15.4: absolute paths no longer accepted by parser.ParseFilesButDoNotLink
Here’s a small test program that breaks when upgrading:

```
% cat repro.go
package main

import (
	"log"
	"os"
	"path/filepath"

	"github.com/jhump/protoreflect/desc/protoparse"
)

func main() {
	tempdir, err := os.MkdirTemp("", "protoparse")
	if err != nil {
		log.Fatal(err)
	}
	if err := os.WriteFile(filepath.Join(tempdir, "extra.proto"), []byte("package extra;"), 0644); err != nil {
		log.Fatal(err)
	}
	mainPath := filepath.Join(tempdir, "main.proto")
	if err := os.WriteFile(mainPath, []byte("package main; import \"extra.proto\";"), 0644); err != nil {
		log.Fatal(err)
	}
	parser := protoparse.Parser{
		ImportPaths: []string{tempdir},
	}

	fds, err := parser.ParseFilesButDoNotLink(mainPath)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("got %d fds", len(fds))
}

% cat go.mod
module protoparse1

go 1.21.5

require github.com/jhump/protoreflect v1.14.1 // indirect

% go run repro.go
2024/01/19 16:31:20 got 1 fds

% go get github.com/jhump/protoreflect@v1.15.4
go: upgraded github.com/jhump/protoreflect v1.14.1 => v1.15.4

% go run repro.go                             
2024/01/19 16:31:24 open /tmp/protoparse337034822/tmp/protoparse337034822/main.proto: no such file or directory
exit status 1
```

Is this change intentional or should the behavioral change be corrected?

Pull request:
desc/protoparse: fix recently identified regressions from v1.14
Fixes #590 and #591.

When v1.15 was implemented, which replaces `desc/protoparse` with thin veneer on top of the `github.com/bufbuild/protocompile` module, a new constraint was inadvertently added, requiring that files explicitly named in `parser.Parse` had to be provided as source and could not be provided as descriptors. But this constraint was not present in v1.14.1 and thus a regression for any code that took advantage of the lack of that constraint.

Similarly, when the `Parser.ParseFilesButDoNotLink` method was re-implemented, it was incorrectly using `Parser.ImportPaths`, despite the Go docs for that field saying they are unused for the "do not link" operation.

This PR fixes both of these regressions, so more code that uses v1.14 can correctly be upgraded to use v1.15.

Patch:
diff --git a/desc/protoparse/parser.go b/desc/protoparse/parser.go
index 6a02bf1..0ab9d1b 100644
--- a/desc/protoparse/parser.go
+++ b/desc/protoparse/parser.go
@@ -241,6 +241,7 @@ func (r noCloneParseResult) Clone() parser.Result {
 // ErrorReporter always returns nil, the parse fails with ErrInvalidSource.
 func (p Parser) ParseFilesButDoNotLink(filenames ...string) ([]*descriptorpb.FileDescriptorProto, error) {
 	rep := newReporter(p.ErrorReporter, p.WarningReporter)
+	p.ImportPaths = nil // not used for this "do not link" operation.
 	res, _ := p.getResolver(filenames)
 	results, err := parseToProtos(res, filenames, reporter.NewHandler(rep), p.ValidateUnlinkedFiles)
 	if err != nil {
@@ -555,16 +556,9 @@ func (p Parser) getResolver(filenames []string) (protocompile.Resolver, *ast2.So
 		}))
 	}
 	backupResolver := protocompile.WithStandardImports(importResolver)
-	mustBeSource := make(map[string]struct{}, len(filenames))
-	for _, name := range filenames {
-		mustBeSource[name] = struct{}{}
-	}
 	return protocompile.CompositeResolver{
 		sourceResolver,
 		protocompile.ResolverFunc(func(path string) (protocompile.SearchResult, error) {
-			if _, ok := mustBeSource[path]; ok {
-				return protocompile.SearchResult{}, os.ErrNotExist
-			}
 			return backupResolver.FindFileByPath(path)
 		}),
 	}, &srcSpan


Test patch:
diff --git a/desc/protoparse/parser_test.go b/desc/protoparse/parser_test.go
index 15e1eb7..3af1772 100644
--- a/desc/protoparse/parser_test.go
+++ b/desc/protoparse/parser_test.go
@@ -525,3 +525,22 @@ func TestParseInferImportPaths_FixesNestedPaths(t *testing.T) {
 		})
 	}
 }
+
+func TestParseFilesButDoNotLink_DoesNotUseImportPaths(t *testing.T) {
+	tempdir, err := os.MkdirTemp("", "protoparse")
+	testutil.Ok(t, err)
+	defer func() {
+		_ = os.RemoveAll(tempdir)
+	}()
+	err = os.WriteFile(filepath.Join(tempdir, "extra.proto"), []byte("package extra;"), 0644)
+	testutil.Ok(t, err)
+	mainPath := filepath.Join(tempdir, "main.proto")
+	err = os.WriteFile(mainPath, []byte("package main; import \"extra.proto\";"), 0644)
+	testutil.Ok(t, err)
+	p := Parser{
+		ImportPaths: []string{tempdir},
+	}
+	fds, err := p.ParseFilesButDoNotLink(mainPath)
+	testutil.Ok(t, err)
+	testutil.Eq(t, 1, len(fds))
+}