Skip to content

Commit

Permalink
Externalize suggestions and tips
Browse files Browse the repository at this point in the history
The X::Method::NotFound error is hard to test for.  This commit
adds the "suggestions" and "tips" method, so that one can test for
(not) expected suggestions, and whether any tips were generated.

Also only use numeric weights in suggestions: there was a mix of
strings and integers, that can't be right  :-)
  • Loading branch information
lizmat committed Aug 23, 2020
1 parent b054f9f commit df5b3d5
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions src/core.c/Exception.pm6
Expand Up @@ -153,6 +153,10 @@ my class X::Method::NotFound is Exception {
has $.typename;
has Bool $.private;
has $.addendum;
has $.message is built(False);
has @.suggestions is built(False);
has @.tips is built(False);

# This attribute is an implementation detail. Not to be documented.
has $.in-class-call;

Expand All @@ -162,14 +166,13 @@ my class X::Method::NotFound is Exception {
!! "of type '$.typename'"
}

method message() {
method TWEAK() {
my @message = $.private
?? "No such private method '!$.method' for invocant $.of-type"
!! "No such method '$.method' for invocant $.of-type";

@message.push: $.addendum if $.addendum;

my @tips;
my $indirect-method = $.method.starts-with("!")
?? $.method.substr(1)
!! "";
Expand Down Expand Up @@ -204,7 +207,7 @@ my class X::Method::NotFound is Exception {
sub find_public_suggestion($before, $after --> Nil) {
if $before.fc eq $after.fc {
$public_suggested = 1;
%suggestions{$after} = ""; # assume identity
%suggestions{$after} = 0; # assume identity
}
else {
my $dist := StrDistance.new(
Expand All @@ -213,7 +216,7 @@ my class X::Method::NotFound is Exception {
);
if $dist <= $max_length {
$public_suggested = 1;
%suggestions{$after} = ~$dist;
%suggestions{$after} = $dist;
}
}
}
Expand Down Expand Up @@ -248,41 +251,43 @@ my class X::Method::NotFound is Exception {
);
if $dist <= $max_length {
$private_suggested = 1;
%suggestions{"!$method_name"} = ~$dist
%suggestions{"!$method_name"} = $dist
unless $indirect-method eq $method_name;
}
}
}

if $indirect-method && !$.private && $private_suggested {
@tips.push: "Method name starts with '!', did you mean 'self!\"$indirect-method\"()'?";
@!tips.push: "Method name starts with '!', did you mean 'self!\"$indirect-method\"()'?";
}

if +%suggestions == 1 {
@tips.push: "Did you mean '%suggestions.keys()'?";
@!suggestions = %suggestions.sort(*.value).map(*.key).head(4);

if @!suggestions == 1 {
@!tips.push: "Did you mean '@!suggestions[0]'?";
}
elsif +%suggestions > 1 {
@tips.push: "Did you mean any of these: { %suggestions.sort(*.value)>>.key.head(4).map( { "'$_'" } ).join(", ") }?";
elsif @!suggestions {
@!tips.push: "Did you mean any of these: { @!suggestions.map( { "'$_'" } ).join(", ") }?";
}

if !$indirect-method
&&($private_suggested ^^ $public_suggested)
&& ($private_suggested ^^ $.private)
{
@tips.push: "Perhaps a " ~ ($private_suggested ?? "private" !! "public") ~ " method call must be used."
@!tips.push: "Perhaps a " ~ ($private_suggested ?? "private" !! "public") ~ " method call must be used."
}

if +@tips > 1 {
@tips = @tips.map: "\n" ~ ("- " ~ *).naive-word-wrapper(:indent(" "));
if @!tips > 1 {
@!tips = @!tips.map: "\n" ~ ("- " ~ *).naive-word-wrapper(:indent(" "));
@message.push: ($.addendum ?? "Other possible" !! "Possible") ~ " causes are:";
}
elsif @tips {
@message.push: @tips.shift;
elsif @!tips {
@message.push: @!tips.shift;
}

@message[0] ~= "." if +@message > 1;
@message[0] ~= "." if @message > 1;

@message.join(" ").naive-word-wrapper ~ @tips.join
$!message = @message.join(" ").naive-word-wrapper ~ @!tips.join
}
}

Expand Down

0 comments on commit df5b3d5

Please sign in to comment.