Ответ 1
Уверенность Брюса Боутона верна. Метод GetChangedSpans не должен быть механизмом различения синтаксиса общего назначения, чтобы разделить два дерева синтаксиса, которые не имеют общей истории. Скорее, предполагается, что два дерева, которые были созданы путем редактирования в общее дерево, и определяют, какие части деревьев отличаются из-за изменений.
Если вы взяли свое первое дерево синтаксического анализа и ввели в него новое утверждение как редактирование, тогда вы увидите гораздо меньший набор изменений.
Это может помочь, если я кратко опишу, как работает лексир и парсер Roslyn на высоком уровне.
Основная идея заключается в том, что лексерские "синтаксические токены" и синтаксические деревья, созданные парсером, неизменяемы. Они никогда не меняются. Поскольку они никогда не меняются, мы можем повторно использовать части предыдущих деревьев синтаксического анализа в новых деревьях синтаксического анализа. (Структуры данных, которые имеют это свойство, часто называют "постоянными" структурами данных.)
Поскольку мы можем повторно использовать существующие части, мы можем, например, использовать одно и то же значение для каждого экземпляра данного токена, например class
, который появляется в программе. Длина и содержание каждого токена class
точно совпадают; единственное, что отличает два разных токена class
, - это их мелочи (что окружает их промежутки и комментарии), а также их положение и их родительский элемент - какой более синтаксис node содержит токен.
При анализе блока текста мы генерируем синтаксические токены и деревья синтаксиса в постоянной, неизменной форме, которую мы называем "зеленой" формой. Затем мы завершаем зеленые узлы в "красном" слое. Зеленый слой ничего не знает о позиции, родителях и т.д. Красный слой. (Причудливые имена связаны с тем, что, когда мы впервые нарисовали эту структуру данных на доске, это те цвета, которые мы использовали.) Когда вы создаете редактирование для данного дерева синтаксиса, мы смотрим на предыдущее дерево синтаксиса, идентифицируем узлы, которые изменились, а затем построили новые узлы только по позвоночнику изменений. Все остальные ветки зеленого дерева остаются неизменными.
При различении двух деревьев, в основном, мы делаем разницу между зелеными узлами. Если одно из деревьев было создано путем редактирования другого, то почти все зеленые узлы будут одинаковыми, потому что только спинной хребет был перестроен. Алгоритм древовидной идентификации идентифицирует измененные узлы и обрабатывает затронутые промежутки.
Если два дерева не имеют общей истории, единственными зелеными узлами, которые у них будут общего, являются индивидуальные жетоны, которые, как я уже говорил, используются повсеместно. Каждый зеленый синтаксис более высокого уровня node будет отличаться от зеленого node и поэтому будет отличаться от механизма разности деревьев, даже если его текст одинаков.
Цель этого метода состоит в том, чтобы позволить редактору быстро сделать консервативное предположение о том, какие части текстового буфера должны быть, скажем, перекрашены, после редактирования или отмены, или какой-то такой вещи. Предполагается, что деревья имеют исторические отношения. Цель состоит не в том, чтобы обеспечить механизм текстовых различий общего назначения; для этого есть много отличных инструментов.
Представьте, например, что вы ввели свою первую программу в редактор, а затем выделили все, а затем вставили вторую программу в редактор. Можно было бы разумно ожидать, что редактор не будет тратить время на попытки выяснить, какие части вставного кода оказались идентичными с ранее вставленным кодом. Это может быть очень дорого, и ответ, скорее всего, будет "немного". Скорее, редактор делает консервативное предположение, что весь вложенный регион является совершенно новым и совершенно другим кодом. Он не тратит время, пытаясь сделать соответствия между старым кодом и новым кодом; он репарации и, следовательно, перекрашивает все это.
Если, с другой стороны, вы только что вставили в одном отдельном выражении, то механизм редактирования просто введет редактирование в нужное место. Дерево синтаксического анализа было бы регенерировано повторно используя существующие зеленые узлы, где это возможно, и механизм различий определит, какие промежутки должны быть перекрашены: те, у которых разные зеленые узлы.
Все это имеет смысл?UPDATE:
Ха, по-видимому, мы с Кевином одновременно печатали один и тот же ответ в соседних офисах. Немного дублированных усилий, но я думаю, что оба ответа имеют хорошие перспективы для ситуации.: -)