Использование regexp для индексации файла для imenu, производительность неприемлема - PullRequest
1 голос
/ 25 мая 2011

Я создаю функцию для imenu-create-index-function, для индексации модуля исходного кода, для csharp-mode.el

Работает, но обеспечивает совершенно неприемлемую производительность. Любые советы по исправлению этого?

Фон

Я посмотрел на js.el, который является переподписанным "espresso", теперь включенным, начиная с v23.2, в emacs. Он очень хорошо индексирует файлы Javascript, отлично справляется с анонимными функциями и различными стилями и шаблонами кодирования. Например, в javascript можно сделать:

(function() {
    var x = ... ; 
    function foo() {
       if (x == 1) ...
    }
})();

... для определения области, где x является "частным" или недоступным из другого кода. Это хорошо индексируется с помощью js.el, используя регулярные выражения, и индексирует внутренние функции (анонимные или нет) также в этой области. Работает быстро. Большой модуль может быть проиндексирован менее чем за секунду.

Я пытался следовать аналогичному подходу в режиме csharp, но это немного сложнее. В Js все, что индексируется, является функцией. Таким образом, начальным регулярным выражением является «функция» с некоторыми уточнениями на каждом конце. После того, как найдено вхождение ключевого слова function, есть еще 4 - 8 других регулярных выражений, которые пробуются через looking-at - число зависит от настроек. Хорошая особенность режима js заключается в том, что вы можете включать или выключать регулярные выражения для различных стилей кодирования, чтобы ускорить процесс. «Стили» по умолчанию работают для большей части кода, который я пробовал.

Это не работает в режиме csharp. Он работает , но работает достаточно плохо, чтобы сделать его не очень удобным для использования. Я думаю, что причина этого в том, что

  • в C # нет ключевого слова с одним маркером, так как function ведет себя в javascript. В C # мне нужно искать пространство имен, класс, структуру, интерфейс, перечисление и так далее.

  • существует большая гибкость, с которой можно определять конструкции csharp. В качестве одного примера, класс может определять базовые классы, а также реализованные интерфейсы. Другой пример: тип возвращаемого значения для метода не простая словесная строка, но может быть что-то грязное, например Dictionary<String, List<String>>. Процедура индексирования должна обрабатывать все эти случаи и фиксировать совпадения. Это заставляет его работать неимоверно.

  • Я использую много looking-back. Маркер, который я использую в текущем подходе - это открытая фигурная скобка. Когда я нахожу один из них, я использую looking-back, чтобы определить, является ли curly классом, интерфейсом, перечислением, методом и т. Д. Я прочитал, что looking-back может быть медленным; Мне не ясно, насколько он медленнее, чем, скажем, looking-at.

  • как только я нахожу пару фигурных открытий-закрытий, я звоню narrow-to-region, чтобы проиндексировать, что внутри. не уверен, если это убьет производительность или нет. Я подозреваю, что это не основной виновник, потому что проблемы с производительностью, которые я вижу, происходят в модулях с одним пространством имен и 2 или 3 классами, что означает, что узкий вызывается в 3 или 4 раза.

В чем вопрос?

У меня такой вопрос: Есть ли у вас какие-либо советы по ускорению индексирования по типу имен в буфере C #?

Я рассматриваю:

  • избегая looking-back. Я не знаю точно, как это сделать, потому что когда re-search-forward находит, скажем, ключевое слово class, курсор уже находится в середине объявления класса. looking-back кажется необходимым.

  • вместо использования open-curly в качестве маркера, используйте ключевые слова, такие как enum, interface, namespace, class

  • избегать narrow-to-region

какой-нибудь жесткий совет? Дополнительные предложения?

Что-то, что я пробовал, и я не очень-то в восторге от повторного посещения: создание основанного на вистенте парсера для C # и использование семантики для индексирования. Я обнаружил, что семантика очень, очень (и т.д.) сложна в использовании, труднодоступна и проблематична. У меня некоторое время была семантическая работа, но потом я обновился до версии 23.2, и она сломалась, и я никогда не мог заставить ее работать снова. Простые вещи, такие как индексация ключевого слова пространства имен, заняли очень много времени. Я очень недоволен этим и не хочу пробовать снова.

1 Ответ

0 голосов
/ 26 мая 2011

Я на самом деле не знаю синтаксиса C #, и, не глядя на ваш elisp, трудно дать ответ, но все равно идет.

looking-back может быть смертельно медленным. Это первое, с чем я поэкспериментирую. Одна вещь, которая очень помогает, это использование аргумента limit, скажем, чтобы ограничить ваш поиск началом текущей строки. Другой подход заключается в том, что когда вы нажимаете открытую фигурную клавишу, выполните backward-char, затем backward-sexp (или что-то еще), чтобы перейти к предыдущему слову, а затем используйте looking-at.

.

Возможно, я бы использовал ключевые слова для поиска вместо открытых фигурных. Может быть, что-то вроде (re-search-forward "\\(enum\\|interface\\|namespace\\|class\\)[ \t\n]*{" nil t), затем используйте match-string-no-properties в первой группе захвата, чтобы увидеть, какое из ключевых слов было найдено. Это может помочь и с проблемой looking-back.

Я не знаю, насколько дорогой narrow-to-region, но этого можно избежать, если вы найдете открытое фигурное указание, сделайте save-excursion forward-sexp и сохраните point в качестве ограничения для текущей итерации вашего (я полагаю, рекурсивные) поиски.

...