Closed samchon closed 1 year ago
@jakebailey As you don't want to fill more question contents in the TS issue, I ask you in here issue.
You told me to use ts.getJSDocTags()
function instead of ts.Symbol.getCommentTags()
function. However, the ts.getJSDocTags()
function removes comment that is not matched with formal JSDoc spec. For example, when I write @type int
comment tag, the int
text would be erased in the ts.getJSDocTags()
API.
This is not what I want, as typia
is utilizing comment tags for validation. I can detour it just by parsing comments by myself with ts.getCommentRange()
function. Of course, copying and pasting from typescript/src/services/jsDoc.ts
is also possible. However, it seems something inefficient.
Is there any other way to solve this problem cleary? Am I missing something?
TypeScript team had decided to support formal transform API since v5.2 update.
Just to temper expectations, it's just me proposing this, and it may not actually happen at all. I would't spend too much time on testing this unless you're really bored.
Is there any other way to solve this problem cleary? Am I missing something?
Are you just looking to get the raw JSDoc text?
const range: ts.TextRange = tsc.getCommentRange(node);
const text: string = TsNodeUtil.getSourceFile(tsc)(
node,
).text.substring(range.pos, range.end);
return filter(text).join("\n");
@jakebailey I'm getting raw comment text through getCommentRage()
function like above code. But if it is supported by TS API, it would be much better for typia
, especially generating JSON schema's description
field. By the way, what typia
really wants is Symbol.getCommentTags()
similar function, which does not erase comment like getJSDocTags()
function.
@type int
comment:
Symbol.getCommentTags()
do not erase int
textgetJSDocTags()
function erase the int
text, because it does not follow JsDoc
spec.JSDoc is a property of the declaration, so you should be able to just call ts.getJSDocCommentsAndTags
on the whichever element of symbol.declarations
is the right one. IIRC this is what TypeDoc does, and we made it public in TS 5.1. That's the PR I linked in the proposal thread.
JSDoc is a property of the declaration, so you should be able to just call
ts.getJSDocCommentsAndTags
on the whichever element ofsymbol.declarations
is the right one. IIRC this is what TypeDoc does, and we made it public in TS 5.1. That's the PR I linked in the proposal thread.
I tried the ts.getJSDocCommentsAndTags()
function following your guide, but it also erases int
text from @type int
tag. Currently, I'm avoiding such removal problem through hard coding like below. If try ts.getJSDocCommentsAndTags()
function restoring commented codes, only [ '@type' ]
be printed in console.
https://github.com/samchon/typia/blob/features/ts5.2/src/utils/TsSymbolUtil.ts
I see, then if you want to get at the text, you could just slice the SourceFile based on node.jsDoc.pos
and node.jsDoc.end
. I am not experienced in our JSDoc APIs to know what the right answer is when attempting to use TS to parse out non-standard tags.
Yes, as you say, I'm using String.substring()
on SourceFile
to avoid the problem.
Do you think erasing comment is a spec, or bug? If bug, I'll make a reproducable repo and report by writing issue on TS repo.
The tags we handle are the ones we have types for and store, so I don't know if this is really a bug. @sandersn would know better.
Neither comments nor tags should be erased. Here's an example I tried:
interface Foo {
/** @type int */
type: number
}
and then at the REPL:
> var f = ts.createSourceFile('welove.ts', fs.readFileSync('welove.ts', 'utf8'), ts.ScriptTarget.ESNext, true)
> var jsdoc = ts.getJSDocCommentsAndTags(f.statements[0].members[0])
> jsdoc[0].tags[0].typeExpression.type.typeName.escapedText
'int'
A few comments:
true
in order to set parent pointers; getJSDocCommentsAndTags relies on parent pointers being set. (Now that it's public the JSDoc should say that.) Thanks @jakebailey for helping me with this. If you're creating a full program, you have to request diagnostics since parent pointers are set as part of binding.@type
is parsed according to its normal rules, so int
, even though it won't be resolved by the checker, is available as typeExpression.type
.tagName
and comment
properties. Then you can parse the comment yourself.comment
, remember that its type is string | NodeArray<JSDocComment>
; you get the second alternative when the comment contains a @link
tag, which is rare but could lead to confusing bugs.jsDoc
property on nodes. getJSDocCommentsAndTags do some additional lookup for @param
tags and parameters, but for custom tags it's basically just returns the internal property.interface Foo {
/** @foundation int */
type: number
}
and then at the REPL:
> var f = ts.createSourceFile('welove.ts', fs.readFileSync('welove.ts', 'utf8'), ts.ScriptTarget.ESNext, true)
> var jsdoc = ts.getJSDocCommentsAndTags(f.statements[0].members[0])
> jsdoc[0].tags[0].comment
'int'
@sandersn I wrote same code with you, but the comment
value still be undefined
.
As you know, I can't controll the createSourceFile()
function, because I'm just utilizing TS 5.2 transform API.
May I believe and just wait for @jakebailey to configure setParentNodes
to be true
?
Or is there something else I should do to help?
const entire = tsc.getJSDocCommentsAndTags(node);
for (const elem of entire)
if (tsc.isJSDoc(elem)) {
const typeTag = elem.tags?.[0];
if (
typeTag &&
tsc.isJSDocTypeTag(typeTag) &&
tsc.isTypeReferenceNode(typeTag.typeExpression.type) &&
tsc.isIdentifier(typeTag.typeExpression.type.typeName)
)
console.log({
comment: typeTag.comment,
expression:
typeTag.typeExpression.type.typeName.escapedText.toString(),
});
}
{ comment: undefined, expression: 'int' }
I notice that you call program.getTypeChecker
. Could you call getSemanticDiagnostics on that checker? That should also set parent pointers.
@sandersn
Found ts.Program.getSemanticDiagnostics()
method, but it accepts only ts.SourceFile
typed parameter. Therefore, I could not call ts.Program.getSemanticDiagnostics()
function about the ts.TypeChecker
instance. Instead, changed reproducable repo to call ts.Program.getSemanticDiagnostics()
function about ts.SourceFile
instance, and only empty array be returned.
Of course, if try to call ts.Program.getSemanticDiagnostics(ts.TypeChecker)
function without considering type error, debug failure error
be occured. Also, ts.TypeChecker
does not have getSemanticDiagnostics()
method, either. Am I missing something, or misunderstanding your order?
$ npm start
> reproduce-ts5.2-transform-api-comment-bug@0.1.0 start
> npx tsc --allowPlugins
checker has getSemanticDiagnostics() method? false
Try to call ts.Program.getSemanticDiagnostics(ts.TypeChecker) function...
Error: Debug Failure. False expression.
at D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119434:13
at runWithCancellationToken (D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119411:14)
at getBindAndCheckDiagnosticsForFileNoCache (D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119429:12)
at getAndCacheDiagnostics (D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119712:20)
at getBindAndCheckDiagnosticsForFile (D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119426:12)
at getSemanticDiagnosticsForFile (D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119421:33)
at getDiagnosticsHelper (D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119359:44)
at Object.getSemanticDiagnostics (D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119372:12)
at Object.create (D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\lib\transform.js:29:21)
at D:\github\contributions\reproduce-TS5.2-transform-API-comment-bug\node_modules\typescript\lib\tsc.js:119324:21
--------------------------------------------------
[]
{ comment: undefined, expression: 'int' }
[]
{ comment: undefined, expression: 'uint' }
[]
{ comment: undefined, expression: 'int64' }
Looks like I mis-remembered the API. If you pass a SourceFile to getSemanticDiagnostics, are the jsdoc tags in that source file available afterward.
Here's some API examples: https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API
@sandersn Tried, but comment
be undefined
, too.
Thanks for help, but I should just use ts.SourceFile.text.substring()
method instead.
https://github.com/microsoft/TypeScript/issues/54276
TypeScript team had decided to support formal transform API since v5.2 update.However, as TS v5.2 transform API provides types of
typescript/lib/tsclibrary
instead oftypescript
,typia
must be entirely rewritten. Also, internal API oftypia
would be (not means global functions liketypia.assert<T>()
, but means internal modules likeAssertProgrammer
) entirely changed, therefore 3rd party libraries likenestia
also need break change, too.In such reason, supporting TS 5.2 transform API,
typia
would have another major versionv4
.Release date of TS 5.2 may
2023-08
, buttypia v4
would be released a little bit earlier. It's because nexttypia
will support bothts-patch
and TS 5.2 transform API. When you runnpx typia setup
, it will configuretsconfig.json
file properly considering TS version. If TS version is lower than 5.2,ts-patch
would be utilized. Otherwise, puretypescript
would be utilized.