Определенно! Мы используем комбинацию JUnit, задачи Ant для выполнения их, и , Гудзон для продолжает интеграционные тесты. Работы как очарование.
Механизм IntelliSense в моем сервисном продукте языка UnrealScript сложен, но я дам здесь как можно лучший обзор. Служба языка C # в VS2008 SP1 - моя цель производительности (не зря). Его еще нет, но он достаточно быстрый / точный, чтобы я мог безопасно предлагать предложения после ввода одного символа, не дожидаясь нажатия Ctrl + пробел или ввода пользователем .
(точка). Чем больше информации об этом получат люди [работающие над языковыми услугами], тем лучше будут мои впечатления от использования их продуктов. Есть ряд продуктов, которые я У меня был неудачный опыт работы с тем, что не уделял такого пристального внимания деталям, и в результате я боролся с IDE больше, чем кодировал.
В моей языковой службе это выглядит следующим образом:
aa.bb.cc
, но может также содержать вызовы методов, как в aa.bb (3 + 2) .cc
. IDeclarationProvider
, где вы можете вызвать GetDeclarations ()
, чтобы получить IEnumerable
всех элементов, видимых в области. В моем случае этот список содержит локальные переменные / параметры (если в методе), члены (поля и методы, только статические, если только в методе экземпляра, и нет закрытых членов базовых типов), глобальные переменные (типы и константы для языка I работаю над) и ключевыми словами. В этом списке будет элемент с именем aa
. В качестве первого шага в оценке выражения в №1 мы выбираем элемент из контекстного перечисления с именем aa
, что дает нам IDeclaration
для следующего шага. ID
, представляющему aa
, чтобы получить другой IEnumerable
, содержащий «элементы» (в некотором смысле) aa
. Начиная с .
отличается от оператора ->
, я вызываю объявление.GetMembers (".")
и ожидаю, что объект IDeclaration
правильно применит указанный оператор. cc
, где список объявлений может или не может содержать объект с именем cc
. Как я уверен, вы знаете, если несколько элементов начинаются с cc
, они тоже должны появиться. Я решаю эту проблему, взяв окончательное перечисление и пропустив его через мой документированный алгоритм , чтобы предоставить пользователю наиболее полезную возможную информацию. Вот некоторые дополнительные примечания для серверной части IntelliSense:
GetMembers
. Каждый объект в моем кэше может предоставить функтор, который оценивает его члены, поэтому выполнение сложных действий с деревом почти тривиально. List
своих членов , У меня есть список List
, где Name
- это структура, содержащая хеш-код специально отформатированной строки, описывающей член. Есть огромный кеш, который сопоставляет имена объектам. Таким образом, когда я повторно разбираю файл, Я могу удалить все элементы, объявленные в файле, из кеша и заново заполнить его обновленными членами. Из-за того, как сконфигурированы функторы, все выражения немедленно вычисляют новые элементы. IntelliSense "frontend"
По мере того, как пользователь вводит, файл синтаксически неправильный чаще, чем правильный . Таким образом, я не хочу случайно удалять разделы кеша, когда пользователь вводит текст. У меня есть большое количество правил для особых случаев, чтобы как можно быстрее обрабатывать инкрементные обновления. Инкрементный кеш хранится только локально в открытом файле и помогает гарантировать, что пользователь не осознает, что их ввод заставляет внутренний кеш хранить неверную информацию о строках / столбцах для таких вещей, как каждый метод в файле.
Фрагмент кода для предыдущего раздела:
class A
{
int x; // linked to A
void foo() // linked to A
{
int local; // linked to foo()
// foo() ends here because bar() is starting
void bar() // linked to A
{
int local2; // linked to bar()
}
int y; // linked again to A
Я решил добавить список функций IntelliSense, которые я реализовал с помощью этого макета. Фотографии каждого из них находятся здесь.
Я не могу точно сказать, какие алгоритмы используются в какой-либо конкретной реализации, но я могу сделать некоторые обоснованные предположения. trie - очень полезная структура данных для этой проблемы: IDE может поддерживать большое дерево в памяти всех символов в вашем проекте с некоторыми дополнительными метаданными на каждом узле.
Когда вы печатаете персонаж, он идет по тропинке в дереве. Все потомки конкретного trie-узла являются возможными дополнениями. Затем IDE просто нужно отфильтровать их по тем, которые имеют смысл в текущем контексте, но ему нужно вычислить только столько, сколько может быть отображено во всплывающем окне завершения табуляции.
Более продвинутое завершение табуляции требует более сложного дерева. Например, Visual Assist X имеет функцию, с помощью которой вам нужно вводить только заглавные буквы символов CamelCase - например, если вы вводите SFN, он показывает вам символ SomeFunctionName
в своем окно завершения табуляции.
Вычисление дерева (или других структур данных) требует синтаксического анализа всего вашего кода, чтобы получить список всех символов в вашем проекте. Visual Studio хранит это в своей базе данных IntelliSense, файле .ncb
, который хранится вместе с вашим проектом, поэтому ему не нужно заново анализировать все каждый раз, когда вы закрываете и снова открываете свой проект. Когда вы впервые открываете большой проект (скажем, тот, который вы только что синхронизировали с системой управления версиями), VS потребуется время, чтобы проанализировать все и сгенерировать базу данных.
Я не знаю, как он обрабатывает инкрементные изменения. Как вы сказали, когда вы пишете код, это неверный синтаксис в 90% случаев, и повторный анализ всего, когда вы простаиваете, приведет к огромному налогу на ваш процессор с очень небольшой выгодой, особенно если вы изменяете файл заголовка, включенный большое количество исходных файлов.
Я подозреваю, что он либо (а) повторно анализирует, когда вы действительно создаете свой проект (или, возможно, когда вы его закрываете / открываете), либо (б) он выполняет какой-то локальный анализ там, где он анализирует только код в том месте, где вы только что отредактировали, в некоторой ограниченной степени, просто чтобы получить имена соответствующих символов. Поскольку C ++ обладает такой чрезвычайно сложной грамматикой, он может вести себя странно в темных углах, если вы: