Подтвердить что ты не робот

Заменить комментарий в JavaScript AST с поддеревом, полученным из содержимого комментария

Я автор doctest, быстрый и грязный доктрины для JavaScript и CoffeeScript. Я хотел бы сделать библиотеку менее грязной, используя парсер JavaScript, а не регулярные выражения для поиска комментариев.

Я хотел бы использовать Esprima или Acorn, чтобы сделать следующее:

  • Создайте AST
  • Пройдите дерево, и для каждого комментария node:
    • Создайте AST из комментария node text
    • Заменить комментарий node в главном дереве с помощью этого поддерева

Ввод:

!function() {

  // > toUsername("Jesper Nøhr")
  // "jespernhr"
  var toUsername = function(text) {
    return ('' + text).replace(/\W/g, '').toLowerCase()
  }

}()

Вывод:

!function() {

  doctest.input(function() {
    return toUsername("Jesper Nøhr")
  });
  doctest.output(4, function() {
    return "jespernhr"
  });
  var toUsername = function(text) {
    return ('' + text).replace(/\W/g, '').toLowerCase()
  }

}()

Я не знаю, как это сделать. Acorn предоставляет walker, который принимает тип и функцию node и выполняет дерево, вызывающее функцию каждый раз, когда встречается node указанного типа. Это кажется многообещающим, но не относится к комментариям.

С Esprima я могу использовать esprima.parse(input, {comment: true, loc: true}).comments для получения комментариев, но я не уверен, как обновлять дерево.

4b9b3361

Ответ 1

Большинство аналитиков, производящих АСТ, бросают комментарии. Я не знаю, что делают Esprima или Acorn, но это может быть проблемой.

.... Фактически, Esprima перечисляет захват комментариев как текущую ошибку: http://code.google.com/p/esprima/issues/detail?id=197

... Желудочный код находится прямо в GitHub. Похоже, что он тоже отсылает комментарии.

Итак, похоже, что вы можете исправить либо синтаксический анализатор, чтобы сначала записать комментарии, и в какой момент ваша задача должна быть простой, или вы застряли.

В нашем DMS Software Reengineering Toolkit есть парсеры JavaScript, которые фиксируют комментарии в дереве. Он также содержит парсы для подстроки языка, которые могут использоваться для анализа текста комментария в JavaScript AST, любого типа, который представляет комментарий (например, объявление функции, выражение, объявление переменной)... и механизм поддержки для прививки таких новых АСТ в основное дерево. Если вы собираетесь манипулировать АСТ, эта возможность подстроки, вероятно, важна: большинство парсеров не будут анализировать фрагменты произвольного языка, они проводятся только для анализа "целых программ". Для DMS нет узлов комментариев для замены; есть комментарии, связанные с узлами AST, поэтому процесс трансплантации немного сложнее, чем просто "заменить узлы комментариев". Все еще довольно легко.

Я понаблюдаю, что большинство парсеров (включая их) читают источник и разбивают его на токены, используя или применяя эквивалент регулярных выражений. Таким образом, если вы уже используете их для поиска комментариев (это означает, что они используют их для поиска * не * комментариев для выброса, например, вам нужно распознать строковые литералы, содержащие текстовые комментарии и игнорировать их), вы так же, как и парсеры, все равно будут искать комментарии. И если все, что вы хотите сделать, это заменить их именно своим контентом, повторение исходного потока с префиксом комментария /suffix/ * */stripped сделает apparantly именно то, что вы хотите, поэтому весь этот механизм синтаксического анализа кажется излишним.

Ответ 2

Вы уже можете использовать Esprima для достижения того, чего хотите:

  • Разберите код, получите комментарии (в виде массива).
  • Итерации над комментариями, посмотрите, интересует ли вас каждый из них.
  • Если вам нужно преобразовать комментарий, обратите внимание на его диапазон. Соберите все преобразования.
  • Применить преобразование назад к первому, чтобы диапазоны не сдвигались.

Трюк здесь не изменяет AST. Просто примените изменение текста, как если бы вы выполняли обычную замену поиска в исходной строке напрямую. Поскольку позиция замены может измениться, вам нужно собрать все, а затем сделать это с последнего. Для примера о том, как выполнить такое преобразование, посмотрите на мой пост в блоге "От двойных кавычек до одиночных кавычек" (это относится к строковым кавычкам, но принцип остается тем же).

И последнее, но не менее важное: вы можете использовать несколько более высокоуровневую утилиту, такую ​​как Rocambole.