Skip to content

Conversation

@powercode
Copy link
Collaborator

PR Summary

Add type inference for Select-Object command

Fixes #7170

PR Checklist

  • [PR has a meaningful title]
  • [Summarized changes]
    This change add type inference for Select-Object in the cases when no projection is done.
    I.E. when neither -Property or -ExcludeProperty is specified.
  • [Change is not breaking]
  • [Make sure all .h, .cpp, .cs, .ps1 and .psm1 files have the correct copyright header]
  • This PR is ready to merge and is not [Work in Progress]
  • User-facing changes
    • Not Applicable
    • Issue filed - Issue link:
  • Testing - New and feature
    • [Make sure you've added a new test if existing tests do not effectively test the code changed]
    • [Add [feature] if the change is significant or affects feature tests]


return expression != null &&
SafeExprEvaluator.TrySafeEval(expression, ExecutionContext, out value) &&
SafeExprEvaluator.TrySafeEval(expression, ExecutionContext, out var value) &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

The PR contains so many style changes that makes it unreasonably large.
Let's leave only significant changes - it will greatly facilitate and speed up the code viewing. Please move style changes in another PR.

Copy link
Collaborator

@BrucePay BrucePay left a comment

Choose a reason for hiding this comment

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

Over all it looks good. I'm still a bit curious about the change from IEnumerable -> List. Also, i think the comments that talk about 'yield' need to be updated.

var list = value as IList;
if (list != null && list.Count > 0)
if (value is IList list && list.Count > 0)
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Extra line?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixing.

var psMethod = member as PSMethod;
var methodCacheEntry = psMethod?.adapterData as DotNetAdapter.MethodCacheEntry;
return methodCacheEntry != null && methodCacheEntry.methodInformationStructures[0].method.IsConstructor;
return psMethod?.adapterData is DotNetAdapter.MethodCacheEntry methodCacheEntry && methodCacheEntry.methodInformationStructures[0].method.IsConstructor;
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is so much going on in this statement that's hard to read. The original code was much easier to follow.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agree! A bit to fast there :)


private IEnumerable<PSTypeName> InferTypesFrom(CommandAst commandAst)
private void InferTypesFrom(CommandAst commandAst, List<PSTypeName> inferredTypes)
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

You should validate that this input is not null.

}
yield break; // yield break;
// Get-CimInstance/New-CimInstance - yields a CimInstance with ETS type based on its arguments for -Namespace and -ClassName parameters
InferTypesFromCimCommand(pseudoBinding, inferredTypes);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since this is no longer and IEnumerable, saying "yield" is a bit weird. Perhaps

Get-CimInstance/New-CimInstance - return a CimInstance with ETS type based on its arguments for -Namespace and -ClassName parameters

if (pseudoBinding.BoundArguments.TryGetValue("Property", out _)
|| pseudoBinding.BoundArguments.TryGetValue("ExcludeProperty", out _))
{
return;
Copy link
Collaborator

Choose a reason for hiding this comment

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

If the argument to -Property is a set of literal strings (most common case), then you could infer the "type" of the output object from them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes. I discussed this a bit with Jason.
We don't currently have a good representation for this, but I would like to have that.
Same thing when you create a PSCustomObject from a hashtable.

But maybe something like "PSObject#Prop1/Prop2/Prop3"

It wouldn't say anything about the types of the properties, but that could maybe be encoded as well.


private IEnumerable<PSTypeName> InferTypesFrom(CommandAst commandAst)
private void InferTypesFrom(CommandAst commandAst, List<PSTypeName> inferredTypes)
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why the change from IEnumerable to List?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand too why we add the allocations.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Mostly debugability. It was a nightmare with all the nested state machines.

But since you have an allocation and virtual dispatch on every generated statemachine class that is generated when we use yield, my guess is that we actually have fewer allocations now.

And in general, I think the code got simpler. Several instances of loops that just yielded the loop object that just disappeared.

If you want to do the exercise, try debugging a tab completion before and after the change.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, debugging can be a headache here.

As for allocations my understanding is that it depends on how we access the object - if we use IEnumerable interface we allocate in both cases, if we cast to a collection we don't allocate I believe.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

But there is no underlying collection to cast to. All the methods here that yield only has the generated state machine classes.

@powercode
Copy link
Collaborator Author

I don't think the Travis build failure has anything to do with this PR.

@iSazonov
Copy link
Collaborator

@powercode Please look CodeFactor issues.

@iSazonov
Copy link
Collaborator

@powercode As for CodeFactor issues.
Many thanks that you fix ALL issues!!!

Really our policy is flexible:

  • we don't ask fix all issues - only ones in new and changed code
  • if you is very busy you can ask maintainers to skip CodeFactor issues - we'll fix them ourselves later.
  • if you do many changes it is better fix style issues in separate PR or add first separate commit with style changes.

Thanks again for your contribution!

@iSazonov
Copy link
Collaborator

Restart CI Travis Linux.

@anmenaga
Copy link

@TravisEz13 this looks ready; pls take a look when you can.

@TravisEz13 TravisEz13 merged commit 3c079b9 into PowerShell:master Jul 2, 2018
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.

5 participants