Я не могу точно сказать, какие алгоритмы используются в какой-либо конкретной реализации, но могу сделать некоторые обоснованные предположения. Trie очень полезная структура данных для этой проблемы: IDE может поддерживать большой в памяти синтаксического дерева всех символов в вашем проекте, с некоторыми дополнительными метаданными на каждом узле.
Когда вы вводите символ, он идет по тропинке в дереве. Все потомки конкретного trie-узла являются возможными дополнениями. Затем IDE просто нужно отфильтровать их по тем, которые имеют смысл в текущем контексте, но ей нужно только вычислить столько, сколько может быть отображено во всплывающем окне завершения табуляции.
Более продвинутое завершение табуляции требует более сложного дерева. Например, Visual Assist X имеет функцию, при которой вам нужно вводить только заглавные буквы символов CamelCase - например, если вы вводите SFN, он показывает вам символ SomeFunctionName
в своем окне завершения табуляции.
Вычисление дерева (или других структур данных) требует синтаксического анализа всего вашего кода, чтобы получить список всех символов в вашем проекте. Visual Studio хранит это в своей базе данных IntelliSense, .ncb
файле, который хранится вместе с вашим проектом, поэтому ему не нужно повторно анализировать все каждый раз, когда вы закрываете и снова открываете свой проект. В первый раз, когда вы откроете большой проект (скажем, тот, который вы только что синхронизировали с системой управления версиями), VS потребуется время, чтобы проанализировать все и сгенерировать базу данных.
Я не знаю, как он обрабатывает постепенные изменения. Как вы сказали, когда вы пишете код, это неверный синтаксис в 90% случаев, и повторный анализ всего, когда вы простаиваете, приведет к огромному налогу на ваш процессор с очень небольшой выгодой, особенно если вы изменяете файл заголовка, включенный большое количество исходных файлов.
Я подозреваю, что он либо (а) только повторно анализирует, когда вы действительно создаете свой проект (или, возможно, когда вы его закрываете / открываете), либо (б) он выполняет своего рода локальный синтаксический анализ, где он анализирует только код там, где вы только что отредактировано ограниченным образом, чтобы получить имена соответствующих символов. Поскольку C ++ имеет такую чрезвычайно сложную грамматику, он может вести себя странно в темных углах, если вы используете тяжелое метапрограммирование шаблонов и тому подобное.