microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.14k stars 12.5k forks source link

Printer doesn't print jsDoc comments #18661

Open gregjacobs opened 7 years ago

gregjacobs commented 7 years ago

I'm using the compiler to convert some old JS files into TypeScript (specifically changing our old "classes" into TS/ES6 classes). I'm doing this by getting the original AST, applying some transformations, and then printing out the new AST to code.

JSDoc nodes are parsed just fine and are available in the original AST, but when printing out the AST back to source, they are missing.

TypeScript Version: 2.5.2

Code

Here's an example of just converting a simple class to AST, and trying to print it out again:

const ts = require('typescript');

const fileContents = `
    export class MyClass {
        /**
         * My great documentation
         */
        myMethod() { return 1; }
    }
`;
const sourceFile = ts.createSourceFile('myFile.ts', fileContents, ts.ScriptTarget.ES2017, /* setParentNodes */ false);
const ast = sourceFile.statements[ 0 ];

const resultFile = ts.createSourceFile('newFile.ts', '', ts.ScriptTarget.Latest, /*setParentNodes*/ false, ts.ScriptKind.TS);
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, removeComments: false });
const result = printer.printNode(ts.EmitHint.Unspecified, ast, resultFile);

console.log(result);

Expected behavior:

The result from the Printer should be printed exactly as the input:

export class MyClass {
    /**
     * My great documentation
     */
    myMethod() { return 1; }
}

Actual behavior:

The jsDoc comment is missing:

export class MyClass {
    myMethod() { return 1; }
}

Great job btw with all of the functionality to be able to grab the AST and generate new AST nodes. Many thanks for that!

DanielRosenwasser commented 7 years ago

Hmm, take a look into how we do it in our refactoring: https://github.com/Microsoft/TypeScript/blob/c3199c7772010bfab3c5b7da2d0d2a2cc4010871/src/services/refactors/convertFunctionToEs6Class.ts#L215-L229

and also look into the comment-setting family of functions: https://github.com/Microsoft/TypeScript/blob/30839378ac593386fc0a2a88512e2d26c38f3a24/src/compiler/factory.ts#L2641-L2672

I'm not sure which to use when though to be honest.

DanielRosenwasser commented 7 years ago

Sorry, I think I rushed a bit and misread the initial issue. This doesn't have to do with creating nodes, it's just the printer itself (as described by the title).

Jack-Works commented 7 years ago

Also, we need a way to generate JSDoc comment. Like Typescript.createJSDocNode or something

StfBauer commented 5 years ago

Is there currently anyway around this. I try to merge two JavaScript files and all the comments always get removed through the printer.

muzea commented 5 years ago

I tried to use ts to do the api interface generation. I want to add some comments to the type, so that users can see the tips when using. One of the PropertyDeclarations is something like this

{
  "pos": -1,
  "end": -1,
  "flags": 8,
  "modifierFlagsCache": 0,
  "transformFlags": 0,
  "kind": 154,
  "name": {
    "pos": -1,
    "end": -1,
    "flags": 8,
    "modifierFlagsCache": 0,
    "transformFlags": 0,
    "escapedText": "RegionId",
    "autoGenerateFlags": 0,
    "autoGenerateId": 0
  },
  "type": {
    "pos": -1,
    "end": -1,
    "flags": 8,
    "modifierFlagsCache": 0,
    "transformFlags": 0,
    "kind": 139
  },
  "jsDoc": [
    {
      "pos": -1,
      "end": -1,
      "flags": 8,
      "modifierFlagsCache": 0,
      "transformFlags": 0,
      "kind": 298,
      "comment": "实例所属的地域ID。您可以调用[DescribeRegions](~~25609~~)查看最新的阿里云地域列表。"
    }
  ]
}

But currently, the printer's result still does not contain comments.

hsiaosiyuan0 commented 4 years ago

Hey guys, good news that the NodeFactory is under refactoring, perhaps we can use ts.factory to get a new factory and use that factory to create jsDoc or something more, however we can also print the jsDoc before the 4.0 is released just separating the original print process into two subroutines, one for printing the jsDoc, another for the specified type:


const fn = ts.createFunctionDeclaration()
fn["jsDoc"] = {
  kind: ts.SyntaxKind.JSDocComment,
  tags: [
    {
      kind: ts.SyntaxKind.JSDocTag,
      tagName: ts.createIdentifier("look"),
      comment: "at you",
    },
  ],
};
printNode(fn['jsDoc']);
printNode(fn);