TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Added typeToTypeNode with truncation

Open armanio123 opened this issue 1 year ago • 9 comments

Fixes https://github.com/microsoft/TypeScript/issues/59168#issuecomment-2212598317

Make completions and formatting handle truncation gracefully. In this PR, when truncation is reported instead tsserver will replace the type with any type. This should also solved the issue mentioned by @weswigham in this comment https://github.com/microsoft/TypeScript/pull/58719#issuecomment-2142734097 about force truncation after 1,000,000 characters.

armanio123 avatar Jul 17 '24 21:07 armanio123

Codecov Report

Attention: Patch coverage is 97.95918% with 1 line in your changes missing coverage. Please review.

Please upload report for BASE (main@972e9a7). Learn more about missing BASE report.

Files Patch % Lines
src/services/codefixes/helpers.ts 97.82% 0 Missing and 1 partial :warning:
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #59332   +/-   ##
=======================================
  Coverage        ?   94.07%           
=======================================
  Files           ?      587           
  Lines           ?   300872           
  Branches        ?     5080           
=======================================
  Hits            ?   283044           
  Misses          ?    12748           
  Partials        ?     5080           

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov-commenter avatar Jul 18 '24 00:07 codecov-commenter

@weswigham I don't understand how to fix the createTypeNodesFromResolvedType. We want to report an error when creating a declaration for a type correct?

i.e the code from test hugeDeclarationOutputGetsTruncatedWithError.ts shows the error The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.

// @declaration: true
type props = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";

type manyprops = `${props}${props}`;

export const c = [null as any as {[K in manyprops]: {[K2 in manyprops]: `${K}.${K2}`}}][0];

because c resolves to:

>c : { aa: { aa: "aa.aa"; ... 527 more ...; zz: { ...; }; }

we can instead resolve c to something like any or { [key: string]: any } but seems to me like this might be incorrect

armanio123 avatar Aug 09 '24 22:08 armanio123

We want to report an error when creating a declaration for a type correct?

Truncations already report a truncation error (via reportTruncationError) which the caller may/may not ignore - if the caller is ignoring it, but has indicated they need syntactically valid output by setting NoTruncation, we should probably emit something other than ... 527 more ..., yes. I wouldn't go with an index signature, though - maybe... something like /*... 527 more ...*/ as a trailing comment to the prior member?

weswigham avatar Aug 15 '24 19:08 weswigham

yes. I wouldn't go with an index signature, though - maybe... something like /... 527 more .../ as a trailing comment to the prior member?

Do you find feasible to do c: /* elided */ any instead of commenting the additional ones? I think that we can check for truncation happening on createTypeNodeFromObjectType and use the same "elided" logic. I actually prefer to have the same behavior when NoTruncation is happening.

armanio123 avatar Aug 15 '24 23:08 armanio123

To your comment about typeToString, doesn't seem to me like we need to fix this method. Unless I'm understanding it wrong, the result of typeToString is a string to be used in errors, display parts, or other places that servers as documentation. Having being truncated by using ... sounds more usefull.

armanio123 avatar Aug 15 '24 23:08 armanio123

I actually prefer to have the same behavior when NoTruncation is happening.

Yeah, I generally do, too, that's why usually it all goes through the createElidedInformationPlaceholder helper usually - but that location has some extra formatting to include the number of skipped elements in the output (since that location isn't skipping a type node, but rather is skipping some number of property declarations), so doesn't. Seems like we aughta retain that? I think it looks a bit nicer to have the count in that position anyway, and it's not like a random type node is syntactically valid there, so you need some kind of special handling. To be clear, what I'm saying is that rather than

>c : { aa: { aa: "aa.aa"; ... 527 more ...; zz: { ...; }; }

when NoTruncation is set, we could emit

>c : { aa: { aa: "aa.aa"; /*... 527 more ...*/ zz: { /*elided*/ }; }

attaching the elision text as a (trailing) comment to the last successful node, rather than inserting the syntactically invalid node or a bogus property/signature.

weswigham avatar Aug 16 '24 00:08 weswigham

Changed as requested. I still have to figure out how to handle the zz: { /*elided*/ } scenario.

armanio123 avatar Aug 16 '24 00:08 armanio123

Looks like you're introducing a change to the public API surface area. If this includes breaking changes, please document them on our wiki's API Breaking Changes page.

Also, please make sure @DanielRosenwasser and @RyanCavanaugh are aware of the changes, just as a heads up.

typescript-bot avatar Aug 19 '24 22:08 typescript-bot

It'd also be nice to add a test case that actually hits the createNotEmittedTypeElement

I don't seem to find a way to create a declaration file with an error like truncation, so I've been testing it locally by removing the error itself. There's an ongoing thread about this here https://github.com/microsoft/TypeScript/issues/54305

armanio123 avatar Aug 21 '24 23:08 armanio123