Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/unreleased/missing-feature-nearest.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- The `missing-feature` error's "did you mean" offers the features nearest to the missing segment by edit distance; it listed the first three alphabetically, so an element with four or more features could be told to try a name unlike the one the query spelt.
3 changes: 2 additions & 1 deletion internal/doc/queryexec/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ func (e *Error) missingFeatureMessage() string {
if len(e.Candidates) > 0 {
msg += ": its features are " + strings.Join(e.Candidates, ", ")
if len(e.Candidates) > 3 {
msg = suggest.With(msg, e.missingSegment(), e.Candidates)
segment := e.missingSegment()
msg = suggest.With(msg, segment, suggest.Nearest(segment, e.Candidates))
}
}
if len(e.Also) > 0 {
Expand Down
27 changes: 27 additions & 0 deletions internal/doc/queryexec/missing_feature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,30 @@ calc def Runs :> Query {
t.Fatalf("frontier features = %+v", failure.Frontier.Features)
}
}

// TestExecuteMissingFeatureSuggestsTheNearestFeatures: the suggestion after the
// feature list ranks by edit distance from the missing segment, not list order.
func TestExecuteMissingFeatureSuggestsTheNearestFeatures(t *testing.T) {
fixture := loadExecutionFixture(t, `
part root {
part a { attribute runs = 3; }
part b { attribute count = 1; attribute runa = 2; attribute runb = 2; attribute runz = 2; }
}
calc def Runs :> Query {
in source : Element;
Project(source = OwnedElements(source = source), properties = ("runs"))
}
`)
bindings := Bindings{"source": {ElementValue(fixture.symbol(t, "root"))}}
_, err := fixture.execute(t, "Runs", bindings, Options{})
var executionError *Error
if !errors.As(err, &executionError) || executionError.Kind != ErrorMissingFeature {
t.Fatalf("error = %v, want missing-feature", err)
}
if msg := executionError.Error(); !strings.HasSuffix(msg, "its features are count, runa, runb, runz — did you mean runa, runb or runz?") {
t.Fatalf("message = %q, want the nearest features offered", msg)
}
if nearest := executionError.Outcome.Path.Failures[0].Frontier.Nearest; nearest != "runa" {
t.Fatalf("nearest = %q, want runa", nearest)
}
}
Loading