Я пишу надстройку COM, которая расширяет IDE, в которой она остро нуждается. Здесь задействовано много функций, но давайте сузим их до 2 ради этого поста:
- Существует окно инструментов Code Explorer, которое отображает древовидное представление, которое позволяет пользователю перемещаться по модулям и их членам.
- Существует окно инструментов проверки кода, которое отображает сетку данных, которая позволяет пользователю перемещаться по проблемам кода и автоматически исправлять их.
Оба инструмента имеют кнопку «Обновить», которая запускает асинхронную задачу, которая анализирует весь код во всех открытых проектах; Code Explorer использует результаты синтаксического анализа для построения TreeView , а код Осмотры использует синтаксический анализ результаты поиска проблем коды и отображение результатов в своей DataGridView .
Здесь я пытаюсь поделиться результатами разбора между функциями, чтобы при обновлении Code Explorer Инспекции кода знали об этом и могли обновляться без необходимости повторения работы синтаксического анализа, которую только что сделал Code Explorer. ,
Итак, что я сделал, я сделал свой класс синтаксического анализатора провайдером событий, для которого функции могут зарегистрироваться:
private void _parser_ParseCompleted(object sender, ParseCompletedEventArgs e)
{
Control.Invoke((MethodInvoker) delegate
{
Control.SolutionTree.Nodes.Clear();
foreach (var result in e.ParseResults)
{
var node = new TreeNode(result.Project.Name);
node.ImageKey = "Hourglass";
node.SelectedImageKey = node.ImageKey;
AddProjectNodes(result, node);
Control.SolutionTree.Nodes.Add(node);
}
Control.EnableRefresh();
});
}
private void _parser_ParseStarted(object sender, ParseStartedEventArgs e)
{
Control.Invoke((MethodInvoker) delegate
{
Control.EnableRefresh(false);
Control.SolutionTree.Nodes.Clear();
foreach (var name in e.ProjectNames)
{
var node = new TreeNode(name + " (parsing...)");
node.ImageKey = "Hourglass";
node.SelectedImageKey = node.ImageKey;
Control.SolutionTree.Nodes.Add(node);
}
});
}
И это работает. У меня проблема в том, что ... это работает - я имею в виду, когда проверки кода обновляются, анализатор говорит проводнику кода (и всем остальным): "Чувак, кто-то разбирает, что ты хочешь с этим делать?" " - и когда анализ завершается, парсер говорит слушателям: «Ребята, у меня есть свежие результаты разбора для вас, что вы хотите с этим сделать?».
Позвольте мне показать вам пример, чтобы проиллюстрировать эту проблему:
- Пользователь вызывает Code Explorer, который говорит пользователю: «Держись, я здесь работаю»; Пользователь продолжает работать в IDE, Code Explorer перерисовывает себя, жизнь прекрасна.
- Затем пользователь вызывает проверки кода, которые говорят пользователю «держись, я здесь работаю»; синтаксический анализатор говорит проводнику кода: "Чувак, кто-то разбирает, что ты хочешь с этим сделать?" - Code Explorer говорит пользователю «держись, я здесь работаю»; Пользователь все еще может работать в IDE, но не может перемещаться по Code Explorer, потому что он обновляется. И он ждет завершения проверки кода.
- Пользователь видит проблему с кодом в результатах проверки, которую он хочет устранить; они дважды щелкают, чтобы перейти к нему, подтверждают, что есть проблема с кодом, и нажимают кнопку «Исправить». Модуль был изменен и требует повторного анализа, поэтому проверки кода продолжаются; Обозреватель кода говорит пользователю «держись, я здесь работаю», ...
Видишь, куда это идет? Мне это не нравится, и я уверен, что пользователям это тоже не понравится. Что мне не хватает? Как мне лучше обмениваться результатами анализа между функциями, но при этом оставить пользователю контроль над тем, когда функция должна выполнять свою работу ?
Причина, по которой я спрашиваю, заключается в том, что я решил, что если я отложу реальную работу до тех пор, пока пользователь не решит активно обновлять данные, и не "кэширует" результаты анализа по мере их поступления ... что ж, я бы обновил древовидную структуру и обнаружение проблем с кодом в возможном устаревшем результате анализа ... что буквально возвращает меня к исходной точке, где каждая функция работает со своими собственными результатами анализа: есть ли способ, которым я могу поделиться результатами анализа между функциями и иметь прекрасный UX?
Код C # , но я не ищу код, я ищу концепции .
VBAParser
генерируется ANTLR и дает мне дерево разбора, но функции этого не потребляют. Он RubberduckParser
берет дерево синтаксического анализа, обходит его и выдает объект VBProjectParseResult
, содержащий все Declaration
объекты, для которых все они References
разрешены - это то, что функции принимают для ввода ... так что да, это в значительной степени ситуация "все или ничего". Он RubberduckParser
достаточно умен, чтобы не анализировать модули, которые не были изменены. Но если есть узкое место, дело не в анализе, а в проверках кода.