New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Partially reuse type nodes #58516
Partially reuse type nodes #58516
Conversation
@@ -16,7 +16,7 @@ var x = 1; | |||
/** @type {NS.Nested.Inner} */ | |||
function f(space, peace) { | |||
>f : (space: any, peace: any) => string | number | |||
> : ^ ^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^ | |||
> : ^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does reuse end up being lowered here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original version for JsDoc did fall back to type printing, but it also set the original node on this synthetic type node counting it as a reuse. Falling back to type printing should not count the node as reused in my opinion.
if (isTypeReferenceNode(node) && isInJSDoc(node) && (!existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(node, getTypeFromTypeNode(node)) || getIntendedTypeFromJSDocTypeReference(node) || unknownSymbol === resolveTypeReferenceName(node, SymbolFlags.Type, /*ignoreErrors*/ true))) {
return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node);
}
function serializeTypeName(context: NodeBuilderContext, node: EntityName, isTypeOf?: boolean, typeArguments?: readonly TypeNode[]) { | ||
const meaning = isTypeOf ? SymbolFlags.Value : SymbolFlags.Type; | ||
const symbol = resolveEntityName(node, meaning, /*ignoreErrors*/ true); | ||
if (!symbol) return undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default behavior here is to fall back to serializing the type node when the name doesn't resolve, and usually I'm inclined to approve of that approach, but the transpileDeclaration
issues we've been getting have made me keenly aware that most names won't resolve when transpiled under that mode, and you probably want the default behavior to be copy-the-node when the name doesn't resolve rather than print-any (at least if the appropriate node builder context flag is set). This is somewhat reasonable since name-that-does-not-resolve is just any
with more steps to get there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually isn't an issue the way this function is currently used. trackExistingEntityName
will already not error if the symbol is not found and will just return the original name. serializeTypeName
is always used as a fallback, when trackExistingEntityName
fails so it will never be called if the symbol is not resolvable.
I added a test that shows that the types are reused even if the symbol is not found.
@dragomirtitian Do you also wanna copy your tests to the |
1b3e65c
to
4265b4e
Compare
I can copy them, but these tests are not actually isolated declarations compliant and I would not expect these changes to actually work with |
Yeah, I would just suggest the test be added to ensure there's still an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the extra tests - from the issues we've been getting in thus far, it seems like it's probably a good idea going forward to test both the full typecheck behavior and the transpileDeclaration
behavior for anything isolatedDeclarations
-adjacent, so we know the two are consistent.
Fixes #58515