reflect/protoreflect: add FileDescriptor.SourceLocations

This adds minimal support for preserving the source context information.

Change-Id: I4b3cac9690b7469ecb4e5434251a809be4d7894c
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/183157
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/descfmt/desc_test.go b/internal/descfmt/desc_test.go
index b07afac..96000fe 100644
--- a/internal/descfmt/desc_test.go
+++ b/internal/descfmt/desc_test.go
@@ -18,18 +18,15 @@
 		"Name":          true,
 		"FullName":      true,
 		"IsPlaceholder": true,
+		"Options":       true,
 		"ProtoInternal": true,
 		"ProtoType":     true,
 
-		"DescriptorByName": true, // specific to FileDescriptor
-		"DefaultEnumValue": true, // specific to FieldDescriptor
-		"MapKey":           true, // specific to FieldDescriptor
-		"MapValue":         true, // specific to FieldDescriptor
-
-		// TODO: These should be removed or handled.
-		"DescriptorProto":       true,
-		"ExtensionRangeOptions": true,
-		"Options":               true,
+		"SourceLocations":       true, // specific to FileDescriptor
+		"ExtensionRangeOptions": true, // specific to MessageDescriptor
+		"DefaultEnumValue":      true, // specific to FieldDescriptor
+		"MapKey":                true, // specific to FieldDescriptor
+		"MapValue":              true, // specific to FieldDescriptor
 	}
 
 	for rt, m := range descriptorAccessors {
diff --git a/internal/filedesc/desc.go b/internal/filedesc/desc.go
index 20ffd83..59984e8 100644
--- a/internal/filedesc/desc.go
+++ b/internal/filedesc/desc.go
@@ -50,8 +50,9 @@
 		Services   Services
 	}
 	FileL2 struct {
-		Options func() pref.ProtoMessage
-		Imports FileImports
+		Options   func() pref.ProtoMessage
+		Imports   FileImports
+		Locations SourceLocations
 	}
 )
 
@@ -75,6 +76,7 @@
 func (fd *File) Messages() pref.MessageDescriptors     { return &fd.L1.Messages }
 func (fd *File) Extensions() pref.ExtensionDescriptors { return &fd.L1.Extensions }
 func (fd *File) Services() pref.ServiceDescriptors     { return &fd.L1.Services }
+func (fd *File) SourceLocations() pref.SourceLocations { return &fd.L2.Locations }
 func (fd *File) Format(s fmt.State, r rune)            { descfmt.FormatDesc(s, r, fd) }
 func (fd *File) ProtoType(pref.FileDescriptor)         {}
 func (fd *File) ProtoInternal(pragma.DoNotImplement)   {}
diff --git a/internal/filedesc/desc_list.go b/internal/filedesc/desc_list.go
index cd92236..d251991 100644
--- a/internal/filedesc/desc_list.go
+++ b/internal/filedesc/desc_list.go
@@ -276,3 +276,11 @@
 	})
 	return p
 }
+
+type SourceLocations struct {
+	List []pref.SourceLocation
+}
+
+func (p *SourceLocations) Len() int                            { return len(p.List) }
+func (p *SourceLocations) Get(i int) pref.SourceLocation       { return p.List[i] }
+func (p *SourceLocations) ProtoInternal(pragma.DoNotImplement) {}
diff --git a/internal/filedesc/placeholder.go b/internal/filedesc/placeholder.go
index eaf04ee..dbf2c60 100644
--- a/internal/filedesc/placeholder.go
+++ b/internal/filedesc/placeholder.go
@@ -11,10 +11,11 @@
 )
 
 var (
-	emptyNames        = new(Names)
-	emptyEnumRanges   = new(EnumRanges)
-	emptyFieldRanges  = new(FieldRanges)
-	emptyFieldNumbers = new(FieldNumbers)
+	emptyNames           = new(Names)
+	emptyEnumRanges      = new(EnumRanges)
+	emptyFieldRanges     = new(FieldRanges)
+	emptyFieldNumbers    = new(FieldNumbers)
+	emptySourceLocations = new(SourceLocations)
 
 	emptyFiles      = new(FileImports)
 	emptyMessages   = new(Messages)
@@ -44,6 +45,7 @@
 func (f PlaceholderFile) Enums() pref.EnumDescriptors           { return emptyEnums }
 func (f PlaceholderFile) Extensions() pref.ExtensionDescriptors { return emptyExtensions }
 func (f PlaceholderFile) Services() pref.ServiceDescriptors     { return emptyServices }
+func (f PlaceholderFile) SourceLocations() pref.SourceLocations { return emptySourceLocations }
 func (f PlaceholderFile) ProtoType(pref.FileDescriptor)         { return }
 func (f PlaceholderFile) ProtoInternal(pragma.DoNotImplement)   { return }