Skip to content

Fixes #30507 - #32100

Closed
Tim Suchanek (timsuchanek) wants to merge 15 commits into
microsoft:masterfrom
timsuchanek:genericObjectExpressionCompletion
Closed

Fixes #30507#32100
Tim Suchanek (timsuchanek) wants to merge 15 commits into
microsoft:masterfrom
timsuchanek:genericObjectExpressionCompletion

Conversation

@timsuchanek

@timsuchanek Tim Suchanek (timsuchanek) commented Jun 26, 2019

Copy link
Copy Markdown
Contributor

Fixes #30507

I saw, that when the object expression has incorrect properties, that don't exist on the type, the autocompletion works fine.
The decision, if the constraint type should be taken as the default or not is being made in checker.ts:15733 and as this is about 10 function calls deep when coming from https://github.com/microsoft/TypeScript/blob/master/src/services/completions.ts#L1457 I had to introduce a parameter in all these functions that can be passed down.
I saw, that there was already a ContextFlags type, which can be passed in to getContextualType, so I extended it and to make it accessible from the completions.ts, I had to add it to the TSChecker types in https://github.com/microsoft/TypeScript/compare/master...timsuchanek:genericObjectExpressionCompletion?expand=1#diff-4b8bd1eea29904f1be39cd864e1a45c0R3335

Let me know if I could have achieved this in a different way, but after many hours of debugging, this looked like the "most minimal" change to achieve the goal.

I added 2 tests, all tests are green.

@msftclas

Microsoft Contribution License Agreements (msftclas) commented Jun 26, 2019

Copy link
Copy Markdown

CLA assistant check
All CLA requirements met.

@schickling

Copy link
Copy Markdown

Very excited to see this fix! Thanks for your work on this Tim Suchanek (@timsuchanek)!

@timsuchanek

Copy link
Copy Markdown
Contributor Author

Sorry to bother, but maybe Anders Hejlsberg (@ahejlsberg) you can have a look as you introduced the ContextFlags. Not sure if I'm "misusing" them.

@AviVahl

Copy link
Copy Markdown

Does it also fix #28470?

@timsuchanek

Tim Suchanek (timsuchanek) commented Jul 11, 2019

Copy link
Copy Markdown
Contributor Author

Avi Vahl (@AviVahl) from my understanding yes! I'll fix the new conflicts tomorrow, then it's again ready to get merged.

I'll also add your example as a test case.

@timsuchanek
Tim Suchanek (timsuchanek) force-pushed the genericObjectExpressionCompletion branch from 4aaccf6 to 0c38f21 Compare July 12, 2019 09:08
@timsuchanek

Tim Suchanek (timsuchanek) commented Jul 12, 2019

Copy link
Copy Markdown
Contributor Author

Avi Vahl (@AviVahl) I added a fix so that your use-case with the constructor arguments is also supported and also added the 2 examples from #28470 as test cases.

Wesley Wigham (@weswigham) Anders Hejlsberg (@ahejlsberg) can you prioritize this PR so that it doesn't get conflicts with master again? Thanks 🙏

Comment thread src/compiler/checker.ts Outdated
@DanielRosenwasser

Daniel Rosenwasser (DanielRosenwasser) commented Jul 15, 2019

Copy link
Copy Markdown
Member

Tim Suchanek (@timsuchanek) would you also be able to add a test for string literal completions too?

declare function get<T, key: K extends keyof T>(obj: T, key: K): T[K];

get({ hello: 123, world: 456 }, "/**/");

This is one of the most-maddening and longest-standing issues we've had in completions. It would be really great to get this reviewed Anders Hejlsberg (@ahejlsberg) Wesley Wigham (@weswigham) Andrew Branch (@andrewbranch).

@timsuchanek

Tim Suchanek (timsuchanek) commented Jul 16, 2019

Copy link
Copy Markdown
Contributor Author

Daniel Rosenwasser (@DanielRosenwasser) I just simplified the "binary and" statement and also added your example as a test.

Important to note: Your example also worked before my PR, I added it to the tests nonetheless. I didn't touch the code path for string literals, just the code path for object expressions when coming from the completion service.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good to me, so long as others are happy with the public API changes. The failed builds are just API baseline issues after the latest merge with master.

Comment thread src/compiler/checker.ts Outdated
@timsuchanek
Tim Suchanek (timsuchanek) force-pushed the genericObjectExpressionCompletion branch from d5667fa to ff6ceb5 Compare August 14, 2019 12:17
@timsuchanek

Tim Suchanek (timsuchanek) commented Aug 14, 2019

Copy link
Copy Markdown
Contributor Author

Thanks Andrew Branch (@andrewbranch)! Is there a way that I can accept the baselines and add a commit for that?
Locally on my machine the tests succeed, can't reproduce the baseline failure.

@weswigham

Copy link
Copy Markdown
Member

Pass --skipPercent=0, and, failing that, set the CI environment variable.

@weswigham

Copy link
Copy Markdown
Member

(also rebase/merge with master)

@andrewbranch

Copy link
Copy Markdown
Member

I fixed the baseline merge. Wesley Wigham (@weswigham) Anders Hejlsberg (@ahejlsberg) any reservations about exporting ContextFlags in the public API?

@schickling

Copy link
Copy Markdown

Thanks a lot Andrew Branch (@andrewbranch). Can’t wait to see this merged! (This is a big deal for us at Prisma (@prisma).) 🎉

*/
runWithCancellationToken<T>(token: CancellationToken, cb: (checker: TypeChecker) => T): T;
}
export enum ContextFlags {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this as well as new signature need to be internal

@timsuchanek Tim Suchanek (timsuchanek) Sep 10, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do you mean we should use something different than the ContextFlags when calling the code from the completion service to prevent this type being exposed?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think Sheetal means to move ContextFlags into one of the ts namespaces that’s already marked /** @internal */ and then to mark the second parameter of TypeChecker['getContextualType'] as /* @internal */ (or declare it as an internal overload, but the linter might call that an unnecessary overload)

@timsuchanek Tim Suchanek (timsuchanek) Sep 10, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok, makes sense! The overload option indeed makes the linter complain:

ERROR: /Users/tim/code/TypeScript/src/compiler/types.ts:3224:61 unified-signatures These overloads can be combined into one signature with an optional parameter.

The non-overload option, which I wrote like this:

        getContextualType(
            node: Expression,
            /* @internal */ contextFlags?: ContextFlags
        ): Type | undefined;

spits out an invalid typescript.d.ts:

        getRootSymbols(symbol: Symbol): ReadonlyArray<Symbol>;
        getContextualType(node: Expression, 
: Type | undefined;
        /**
         * returns unknownSignature in the case of an error.
         * returns undefined if the node is not valid.
         * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`.
         */

Is there a way to ignore the linter in this case?
Or what is the right way to add @internal to a specific argument?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just filed #33350. I think it would be ok to ignore the line from the linter. Sheetal Nandi (@sheetalkamat)?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes in past we have marked the overload internal and disabled the rule for that line.

@timsuchanek Tim Suchanek (timsuchanek) Sep 11, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Had to adjust the tests because of #32266

Anything else you need from my side to get this merged?
Sheetal Nandi (@sheetalkamat) Andrew Branch (@andrewbranch)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Cool, this doesn’t even touch the public API baselines now. Would be good to get an approval from another person on the team but I think this is good.

@timsuchanek
Tim Suchanek (timsuchanek) force-pushed the genericObjectExpressionCompletion branch from a118dc5 to 85ee123 Compare September 11, 2019 08:36
@timsuchanek
Tim Suchanek (timsuchanek) force-pushed the genericObjectExpressionCompletion branch from 85ee123 to 7883ec6 Compare September 11, 2019 08:48
Comment thread src/compiler/checker.ts
const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper);
if (!inferredType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
const isCompletionContext = contextFlags && (contextFlags & ContextFlags.Completion);
if (!inferredType || isCompletionContext || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't seem like the right place to do this - rather than passing the flag all the way thru signature resolution, if this flag is set, we should just look at the "base signature" (getBaseSignature) rather than starting inference at all, I think. Then again, if we did that we wouldn't get an instantiated constraint which reports more detailed information on circular constraints. Then again again, I'm pretty sure as-is this is caching into the resolvedSignature of a node, which this very much is not - which means requesting completions poisons the cache with incorrect types for later checking.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the feedback Wesley Wigham (@weswigham)! Do you have a suggestion how we still could fix the autocompletion for this? This was, unfortunately, the only way I found (with my limited knowledge of the codebase).

Maybe introducing a new method as an alternative to getContextualType just to be used by the completion service?

@weswigham Wesley Wigham (weswigham) Sep 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think getContextualType is still right, we just need to avoid using any resolved signature caches.

@orta

Copy link
Copy Markdown
Contributor

TypeScript Bot (@typescript-bot) pack this

@typescript-bot

TypeScript Bot (typescript-bot) commented Sep 24, 2019

Copy link
Copy Markdown
Contributor

Heya Orta Therox (@orta), I've started to run the tarball bundle task on this PR at 96a782e. You can monitor the build here. It should now contribute to this PR's status checks.

@andrewbranch

Copy link
Copy Markdown
Member

Hey Tim Suchanek (@timsuchanek), I took a stab at addressing Wesley Wigham (@weswigham)’s concerns with some guidance from Daniel Rosenwasser (@DanielRosenwasser). I didn’t want to push a more substantial change here so I branched off of this PR and pushed a new one up at #33937. Would greatly appreciate your input there. Thanks!

@andrewbranch

Copy link
Copy Markdown
Member

Tim Suchanek (@timsuchanek), thanks for championing this through! Your commits here have been merged into master via #33937. 🏆

@timsuchanek

Copy link
Copy Markdown
Contributor Author

Thanks a lot, Andrew Branch (@andrewbranch) for pushing this over the finish line!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Autocompletion broken for generic function parameter with optional properties