Почему ts.getJSDocTags никогда не возвращает никаких элементов?

Вот мой код:

const filename = 'example.ts';
const code = `

/** 
 * @description foobar
 * 
 * @see test
 */
class Foo  {};
`;

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

const visitNode = (node: ts.Node) => {
  ts.forEachChild(node, visitNode);
  console.info(ts.SyntaxKind[node.kind], node);
  console.info('--', ts.getJSDocTags(node));
  console.info(
    ts.forEachLeadingCommentRange(
      sourceFile.text,
      node.getFullStart(),
      (pos, end, kind) => {
        console.info(sourceFile.text.slice(pos, end));
      }
    )
  );
};

ts.forEachChild(sourceFile, visitNode);

Я не могу понять, почему все призывы ts.getJSDocTags вернуть товар.

Вот репродукция stackblitz.

Это действительная проблема в Typescript. github.com/microsoft/TypeScript/issues/42895

Art Bindu 19.04.2024 14:42

Проблемы, связанные с JSDocTag: github.com/microsoft/TypeScript/…

Art Bindu 19.04.2024 14:43

@ArtBindu Я считаю, что это не связанная с этим проблема.

Matthieu Riegler 19.04.2024 14:54

Есть это и пример здесь с использованием API из интерфейса symbol.

morganney 21.04.2024 03:32
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
4
4
210
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я отладил ваш пример кода (репродукция stackblitz.) и обнаружил проблему, почему он возвращает empty array в результате ts.getJSDocTags(node).

Пожалуйста, проверьте библиотеку машинописных текстов: node_modules/typescript/lib/tsc.js.

Есть проблема.

Сначала проверьте функцию getJSDocTags, там мы вызываем getJSDocTagsWorker функцию со значением noCache параметров как false.

function getJSDocTags(node) {
  return getJSDocTagsWorker(
    node,
    /*noCache*/
    false
  );
}

Затем проверьте функцию getJSDocTagsWorker.

function getJSDocTagsWorker(node, noCache) {
  var _a;
  if (!canHaveJSDoc(node))
    return emptyArray;
  let tags = (_a = node.jsDoc) == null ? void 0 : _a.jsDocCache;
  if (tags === void 0 || noCache) {
    ... ... ... 
  }
  return tags;
}

Здесь значение tags равно empty array ([]). Потому что, _a.jsDocCache = node.jsDoc.jsDocCache = []. Кроме того, значение noCache равно false

Таким образом, он не входит во второй блок if (tags === void 0 || noCache) и не возвращает значение tags как empty array.

Прикрепил скрин для справки.

Я надеюсь, что это поможет вам.

Вот пример на stackblitz.

Вам необходимо создать программу, а затем использовать средство проверки типов, чтобы получить связанный символ из узла AST. Затем из интерфейса symbol вы можете сослаться на работающую getJSDocTags реализацию.

Учитывая этот файл.ts:

/**
 *
 * @deprecated
 * test
 *
 * @description foobar
 *
 * @see test
 * @param a some comment
 */
class Foo {}

Вы можете создать документацию для тегов JSDoc следующим образом:

(Скажем, это файл main.ts)

import ts from 'typescript';

const generateDocumentation = (
  fileNames: string[],
  options: ts.CompilerOptions
): void => {
  const program = ts.createProgram(fileNames, options);
  const checker = program.getTypeChecker();

  const visit = (node: ts.Node) => {
    if (ts.isClassDeclaration(node) && node.name) {
      const symbol = checker.getSymbolAtLocation(node.name);

      if (symbol) {
        const jsDocTags = symbol.getJsDocTags();

        jsDocTags.forEach((tag) => {
          console.info('--name--', tag.name);
          console.info('--text--', tag.text);
        });
      }
    }
  };

  for (const sourceFile of program.getSourceFiles()) {
    if (!sourceFile.isDeclarationFile) {
      // Walk the tree to search for classes
      ts.forEachChild(sourceFile, visit);
    }
  }
};

generateDocumentation(['file.ts'], {
  target: ts.ScriptTarget.ESNext,
});

Вы можете проверить это, выполнив следующие шаги:

tsc main.ts -m nodenext
node main.js

Или просто используйте tsx и npm run dev.

Ответ принят как подходящий

Решение на самом деле довольно простое. ts.createSourceFile необходимо, чтобы 4-й аргумент setParentNodes?: boolean | undefined был true.

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

Другие вопросы по теме