microsoft / TypeScript

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

`getTextOfJSDocComment` introduces a space in JSDoc comments #59679

Open JeanMeche opened 3 weeks ago

JeanMeche commented 3 weeks ago

πŸ”Ž Search Terms

getJSDocTags getTextOfJSDocComment

πŸ•— Version & Regression Information

Tested on 5.5.4, also existed on previous versions.

⏯ Playground Link

https://stackblitz.com/edit/gettextofjsdoccomment-dbm6rj?file=main.ts,package-lock.json

πŸ’» Code

import ts from 'typescript';

const filename = 'example.ts';
const code = `
/** 
 * 
 * @see {@link entry()}
 */
class Foo  {};
`;

const sourceFile = ts.createSourceFile(
  filename,
  code,
  ts.ScriptTarget.ESNext,
  true
);

const visitNode = (node: ts.Node) => {
  ts.forEachChild(node, visitNode);
  const tags = ts.getJSDocTags(node);
  if (tags.length) {
    tags.forEach((tag) => {
      const comment = tag.comment!.slice(1) as any;

      console.log(
        tag.tagName.getText(),
        '> ',
        ts.getTextOfJSDocComment(comment)
      );

      //console.log(comment);
    });
  }
};

ts.forEachChild(sourceFile, visitNode);

πŸ™ Actual behavior

getTextOfJSDocComment returns {@link entry ()}. Notice the space inbetween.

πŸ™‚ Expected behavior

getTextOfJSDocComment returns {@link entry()}. Notice the space inbetween.

Additional information about the issue

This is a variation of #58584.

Also noticed it happened with {@link core/inject} becoming {@link core /inject}

a-tarasyuk commented 3 weeks ago

The parser handles these cases as

// "entry" - name
// "()"    - text
// "code"    - name
// "/inject" - text

https://github.com/microsoft/TypeScript/blob/936a79bbb58f82b173f6b644974995851b9b479e/src/compiler/utilitiesPublic.ts#L1289

The formatter adds a space between the name and text, with only two cases where the space is omitted. @sandersn, should we add special nodes to the parser, or would it be better to handle these known cases ('/' and '(') directly in the formatter?