Skip to content

Conversation

@juliangiebel
Copy link
Contributor

This is a patch from @moonheart08

This PR adds four new commands:
cmd:accepts = Filters commands based on what type they accept as a piped argument
cmd:accepts_generic = Filters commands based on what type they accept as a piped argument, allowing commands that broadly accept most types

cmd:returns = Filters commands based on what type they return as a result
cmd:returns_generic = Filters commands based on what type they return as a result, allowing commands that broadly accept most types

Comment on lines +30 to +31
// TODO: This should be an optional parameter, --generic, instead.
[CommandImplementation("accepts_generic")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional parameters are supported, though not with the --<argName> syntax, so you're forced to either specify them or use an explicit pipe | to chain the output into another command.

If we want the -- syntax, I guess its fine to keep the TODO, but there should probably be an issue for the missing feature.

var impls = cmd.Cmd.CommandImplementors[cmd.SubCommand ?? string.Empty]
.MethodsByPipedType(pipedArgument, allowGeneric);

var anyNonGeneric = false;
Copy link
Member

@ElectroJr ElectroJr Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT anyNonGeneric is equivalent to fitness >= 1. So IMO it'd be clearer if the bool were just removed, or simply defined using fitness after the foreach block.

Its not really that important, but IMO its a bit more readable.

Comment on lines +57 to +59
fitness = int.Max(fitness, 2); // Exact match
else
fitness = int.Max(fitness, 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just

Suggested change
fitness = int.Max(fitness, 2); // Exact match
else
fitness = int.Max(fitness, 1);
return (cmd, fitness: 2); // Exact match
fitness = 1;

if (pipedType == null)
return false;

return x.Generic || _toolshed.IsTransformableTo(pipedType, param.ParameterType);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets rid of the x.Generic check, which is still needed. IsTransformableTo just doesn't support generics atm and currently still needs to bypass it. IIRC generics are basically handled implicitly further down in the try-catch block with

var t = GetGenericTypeFromPiped(pipedType!, x.PipeArg!.ParameterType);
return (x, x.Info.MakeGenericMethod(typeArguments?.Append(t).ToArray() ?? [t]));

The way toolshed handles generics is just pretty janky overall, it doesn't really handle generic type constraints at all, it just checks it implicitly by seeing if MakeGenericMethod throws. So I think you either need to shuffle logic around to get the a concrete method & parameter types before calling IsTransformableTo, or you just can't quite do this (its currently causing test fails)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants