Typescript: Strip `@internal` from `Symbol.parent` property

Created on 5 May 2020  ·  12Comments  ·  Source: microsoft/TypeScript

Search Terms

API, Symbol, parent

Suggestion

If it's possible, I'd like to strip @internal comment from the Symbol.parent property and get this property in the API.

Is there any reason why it's not in the public API yet or we can just strip it?

Use Cases

I'm working on a custom transformer which needs to know all symbols chain. I'm trying to figure out whether the property is "exported" (or public accessible) via entry point somehow and it looks like Symbol.parent helps me to do it easily (I'm using it right now and it seems to work as expected).

Checklist

My suggestion meets these guidelines:

  • [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [x] This wouldn't change the runtime behavior of existing JavaScript code
  • [x] This could be implemented without emitting different JS based on the types of the expressions
  • [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [x] This feature would agree with the rest of TypeScript's Design Goals.
API

Most helpful comment

What we do in declaration emit is, for a given location, for each symbol table we find as we go up the AST, lexicially, we traverse each symbol in the table to see if it is or can reach (meaning: refers to or contains, transitively) the symbol we're looking for. It's exhaustive and actually the most expensive part of declaration emit. The code we use internally that probably most closely matches what you're looking for is EmitResolver.isSymbolAccessible (which in turn relies on getAccessibleSymbolChain).

All 12 comments

Seconded! TypeDoc does something similar, to determine if a node is exported I walk up node parents until I get to a source file, then try to get the symbol for it.

I walk up node parents until I get to a source file, then try to get the symbol for it.

@Gerrit0 can't you use getSourceFile() method of the Node instead? 🤔

@orta is the PR welcomed here or you need to discuss it first?

@Gerrit0 can't you use getSourceFile() method of the Node instead? 🤔

If I was only looking for the source file, yes. But I also have to deal with namespaces.

@orta is there any chance to have this issue as "help wanted" so I can make a PR?

/cc @weswigham / @rbuckton ^

Afaik it's not public because it's not reliably set - in practice a single symbol may exist in multiple containers simultaneously. The .parent field just tracks the first of them, potentially. It's also not set on local symbols, only exports.

Our logic to generate the possible symbol chains with which you can refer to a symbol is actually quite complicated.

in practice a single symbol may exist in multiple containers simultaneously. The .parent field just tracks the first of them, potentially

@weswigham isn't it the similar as a node's parent (but the only original one, without aliases maybe)?

Every node has a syntactic parent which can be discovered through a top-down traversal. The .parent node property is just a cache of that result, essentially. Nodes only lack .parents when they haven't been traversed to be set yet. (But yes: a .parent for a node only exists in the context of a full AST) This is different than a symbol's .parent, which, thanks to namespace and interface merging, combined with reexporting, never fully captures the full gamut of "things this symbol is considered to reside within". We don't rely solely on it internally for calculating public qualified names for symbols (we also traverse aliases and merged symbols to find equivalent symbols and alternative container symbols) - you _probably_ shouldn't either.

@weswigham thanks for explanation, I got it! So, the better (or even the only correct one) is getting node's symbol, get all the symbol's declarations, take their symbols and so on recursively, right?

What we do in declaration emit is, for a given location, for each symbol table we find as we go up the AST, lexicially, we traverse each symbol in the table to see if it is or can reach (meaning: refers to or contains, transitively) the symbol we're looking for. It's exhaustive and actually the most expensive part of declaration emit. The code we use internally that probably most closely matches what you're looking for is EmitResolver.isSymbolAccessible (which in turn relies on getAccessibleSymbolChain).

@weswigham Thank you a lot again for the explanation, it really helps!

Thus, it seems that we shouldn't use Symbol.parent property and the issue could be closed?

Was this page helpful?
0 / 5 - 0 ratings