Skip to content

feature: use parent source location path if the original one is missing #20

@maratori

Description

@maratori

If I provide a valid source location path to check.WithFileNameAndSourcePath, but it's missing from the file, the annotation points to the file. I would expect the nearest parent to be found for the annotation.

Usually, the path should always exist. However, working with options, this may be the case. For example, the following file contains a path pointing to (x).y but missing a path to (x). In this case, an annotation for message options should be created.

extend google.protobuf.MessageOptions {
  X x = 5000;
}
message X {
  string y = 1;
}
message Foo {
  option (x).y = "z";
}
Go test to reproduce the issue
package x_test

import (
	"context"
	"os"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/require"

	"buf.build/go/bufplugin/check"
	"buf.build/go/bufplugin/check/checktest"
	"buf.build/go/bufplugin/check/checkutil"
	"buf.build/go/bufplugin/descriptor"
)

const protoFile = `
syntax = "proto3";
import "google/protobuf/descriptor.proto";
extend google.protobuf.MessageOptions {
  X x = 5000;
}
message X {
  string y = 1;
}
message Foo {
  option (x).y = "z";
}
`

func TestX(t *testing.T) {
	dir := t.TempDir()
	require.NoError(t, os.WriteFile(filepath.Join(dir, "file.proto"), []byte(protoFile), 0666))
	checktest.CheckTest{
		Request: &checktest.RequestSpec{
			Files: &checktest.ProtoFileSpec{
				DirPaths:  []string{dir},
				FilePaths: []string{"file.proto"},
			},
			RuleIDs: []string{"XXX"},
		},
		Spec: &check.Spec{
			Rules: []*check.RuleSpec{{
				ID:      "XXX",
				Purpose: "X.",
				Type:    check.RuleTypeLint,
				Handler: checkutil.NewFileRuleHandler(
					func(
						_ context.Context,
						writer check.ResponseWriter,
						_ check.Request,
						file descriptor.FileDescriptor,
					) error {
						foo := file.ProtoreflectFileDescriptor().Messages().ByName("Foo")
						writer.AddAnnotation(
							check.WithMessage("X"),
							check.WithFileNameAndSourcePath(
								"file.proto",
								append(
									file.ProtoreflectFileDescriptor().SourceLocations().ByDescriptor(foo).Path,
									7,
									5000,
								),
							),
						)
						return nil
					},
					checkutil.WithoutImports(),
				),
			}},
		},
		ExpectedAnnotations: []checktest.ExpectedAnnotation{{
			RuleID:  "XXX",
			Message: "X",
			FileLocation: &checktest.ExpectedFileLocation{
				FileName:    "file.proto",
				StartLine:   10,
				StartColumn: 2,
				EndLine:     10,
				EndColumn:   21,
			},
		}},
	}.Run(t)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions