Piszę dodatek COM, który rozszerza IDE, które desperacko tego potrzebuje. W grę wchodzi wiele funkcji, ale ograniczmy się do 2 ze względu na ten post:
- Istnieje okno narzędzi Code Explorer, które wyświetla widok drzewa, który pozwala użytkownikowi nawigować po modułach i ich członkach.
- Jest Kontrole Code toolwindow który wyświetla DataGridView , który pozwala poruszać się problemy kodu użytkownika i automatycznie je naprawić.
Oba narzędzia mają przycisk „Odśwież”, który uruchamia asynchroniczne zadanie, które analizuje cały kod we wszystkich otwartych projektach; Code Explorer używa analizowania wyników zbudować katalogów , a kod Kontrole wykorzystuje analizowania wyników, aby znaleźć problemy kodu i wyświetla wyniki w swojej DataGridView .
To, co próbuję tutaj zrobić, to udostępnienie wyników analizy między funkcjami, aby po odświeżeniu Code Explorera , Inspekcje kodu wiedziały o tym i mogły się odświeżyć bez konieczności ponownego wykonywania analizy składniowej, którą właśnie wykonał Code Explorer .
Więc co zrobiłem, uczyniłem moją klasę analizatora składni zdarzeniem, do którego funkcje mogą się zarejestrować:
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);
}
});
}
I to działa. Problem, który mam, polega na tym, że ... działa - to znaczy, kiedy inspekcje kodu są odświeżane, parser mówi eksploratorowi kodu (i wszystkim innym) "koleś, czyjaś analiza, czy chcesz coś z tym zrobić? „ - a kiedy parsowanie się zakończy, parser mówi swoim słuchaczom: „chłopaki, mam dla ciebie świeże wyniki parsowania, cokolwiek chcesz z tym zrobić?”.
Pozwól, że przedstawię ci przykład ilustrujący problem, który to stwarza:
- Użytkownik wywołuje Eksploratora kodu, który mówi użytkownikowi „poczekaj, pracuję tutaj”; użytkownik kontynuuje pracę w IDE, Code Explorer przerysowuje się, życie jest piękne.
- Następnie użytkownik wywołuje Inspekcje kodu, które mówią użytkownikowi „poczekaj, pracuję tutaj”; parser mówi Eksploratorowi kodu „koleś, czyjaś analiza, czy chcesz coś z tym zrobić?” - Code Explorer mówi użytkownikowi „poczekaj, pracuję tutaj”; użytkownik nadal może pracować w środowisku IDE, ale nie może poruszać się po Eksploratorze kodu, ponieważ jest odświeżany. I czeka też na zakończenie kontroli kodu.
- Użytkownik widzi problem z kodem w wynikach kontroli, którą chce rozwiązać; kliknij dwukrotnie, aby przejść do niego, potwierdź problem z kodem i kliknij przycisk „Napraw”. Moduł został zmodyfikowany i musi zostać ponownie przeanalizowany, aby umożliwić kontynuację inspekcji kodu; Code Explorer mówi użytkownikowi „poczekaj, pracuję tutaj”, ...
Widzisz dokąd to zmierza? Nie podoba mi się to i założę się, że użytkownikom też się nie spodoba. czego mi brakuje? Jak powinienem udostępniać wyniki analizy między funkcjami, ale nadal pozostawić kontrolę nad tym, kiedy funkcja powinna działać ?
Powodem, dla którego pytam, jest to, że pomyślałem, że jeśli odłożę rzeczywistą pracę, aż użytkownik aktywnie zdecyduje się odświeżyć, i „buforuję” wyniki analizy, gdy się pojawią… cóż, odświeżyłbym widok drzewa i lokalizowanie problemów z kodem w prawdopodobnie przestarzałym wyniku analizy ... co dosłownie sprowadza mnie z powrotem do punktu wyjścia, gdzie każda funkcja działa z własnymi wynikami analizy: czy jest jakiś sposób, aby udostępnić wyniki analizy między funkcjami i mieć piękny UX?
Kod to c # , ale nie szukam kodu, szukam pojęć .
VBAParser
jest generowany przez ANTLR i daje mi parsowanie, ale funkcje tego nie zużywają. RubberduckParser
Bierze drzewo składniowy, spacery, i zgłosi VBProjectParseResult
, który zawiera Declaration
obiekty, które posiadają wszystkie ich References
rozwiązany - to jakie cechy biorą na wejściu .. tak tak, to dość dużo sytuacja wszystko albo nic. RubberduckParser
Jest wystarczająco inteligentny, aby nie re-parse modułów, które nie zostały zmodyfikowane chociaż. Ale jeśli istnieje wąskie gardło, nie dotyczy to analizowania, lecz kontroli kodu.