Adding JSDoc annotations using type information from the AST

Topics: General
Apr 5, 2014 at 11:59 PM
Edited Apr 6, 2014 at 12:03 AM
(For some context, I compile my TS code using a custom build task that uses the TypeScriptCompiler API instead of of calling tsc. I do this because I run the generated JS and sourcemap strings through other tasks without needing to read and write to intermediate files.)

I was looking for a way to add JSDoc annotations - @constructor, @extends, @memberOf, @private and @static - by walking over the TS AST exposed via TypeScriptCompiler.getDocument(...).syntaxTree().sourceUnit()

The walker is an implementation similar to src/services/getScriptLexicalStructureWalker.ts except that it adds the above JSDoc annotations to the leadingTriviaInfo of AST nodes that need it. For example, if it walks over a class declaration that has an extends clause, it adds * @extends {namespace.BaseClass} to its leadingTriviaInfo comment.

When doing this using typescript.js built from the develop branch, I was able to modify node._fullText and node._leadingTriviaInfo (calculating the latter appropriately - shift by 2 and OR the flags from the lower two bits). Then calling compiler.compile(...) would generate JS that included the added annotations.

But this doesn't work with 1.0.0 (1.0.0 also seems to use the old syntax tree structure and API that was in 0.9.x instead of what develop has). compiler.compile() eventually fails with this:
Error: Argument out of range: position
    at Function.Errors.argumentOutOfRange (evalmachine.<anonymous>:1168:20)
    at LineMap.fillLineAndCharacterFromPosition (evalmachine.<anonymous>:1868:41)
    at Emitter.recordSourceMappingStart (evalmachine.<anonymous>:31177:25)
    at Emitter.emitIfStatement (evalmachine.<anonymous>:32286:18)
    at Emitter.emitWorker (evalmachine.<anonymous>:32752:33)
    at Emitter.emit (evalmachine.<anonymous>:32658:18)
    at Emitter.emitJavascript (evalmachine.<anonymous>:31581:18)
    at Emitter.emitList (evalmachine.<anonymous>:31324:26)
It appears to be in code related to generating the sourcemap from the AST. (The line numbers correspond to typescript.js in the npm package.)

Of course I understand fiddling with the lengths of individual nodes probably violates the data structures' invariants and it's understandable that it breaks the compiler, but is there a better (proper) way to do this (edit the trivia info of AST nodes)?
Apr 7, 2014 at 4:33 AM
I managed to do this by overriding Emitter.prototype.emitComments instead. In it, before calling the original implementation, I change the value of ast.preComments()[0]._trivia._fullText and ._fullWidth. This doesn't cause the error in the OP and the generated sourcemaps are fine too.

Still looking for a proper way to do this, if any.