Что вы, кажется, нужно это анализатор для вашего языка (Java), а также распознаватель имен и типов. («Конструктор таблиц символов»).
После разбора исходного текста у компилятора обычно есть распознаватель имен, который пытается записать определение имен и их соответствующих типов и средство проверки типов, которое проверяет, что каждое выражение имеет допустимый тип.
Обычно распознаватель имен/типов жалуется, когда он не может найти определение. То, что вы хотите, это найти «неопределенную» вещь, которая вызывает проблему, и вывести для нее тип.
Для
IPerson p = new Person();
имя распознавателя знает, что "лицо" и "IPerson" не определены. Если бы это было
Foo p = new Bar();
не было бы никакой подсказки, что вы хотели интерфейс, только что Foo является своим родом абстрактного родителя Бара (например, класс или интерфейс). Поэтому решение, которое должно быть известно этому инструменту («всякий раз, когда вы найдете такую конструкцию, предположим, что Foo - это интерфейс ...»). Вы можете использовать эвристику: IFoo и Foo означает, что IFoo должен быть интерфейсом, и где-то кто-то должен определить Foo как класс, реализующий этот интерфейс. После того, как инструмент принял это решение, то ему необходимо будет обновить свои таблицы символов, так что он может перейти на другие заявления:
Для
p.Name = "Sklivvz";
при условии, что р должен быть интерфейс (по предыдущий вывод), тогда Имя должно быть членом поля, и, как представляется, его тип - это String из присваивания.
При том, что утверждение:
Assert.AreEqual("Sklivvz", p.Name);
имена и типы разрешиться без дополнительного выпуска.
Содержание объектов IFoo и Foo является своего рода достоянием; вам не пришлось использовать get и set, но это личный вкус.
Это не будет работать так хорошо, когда у вас есть несколько объектов в том же заявлении:
x = p.a + p.b ;
Мы знаем и б вероятные поля, но вы не можете догадаться, что числовой тип, если на самом деле они являются numeric, или если они являются строками (это законно для строк в Java, dunno о C#). Для C++ вы даже не знаете, что означает «+»; это может быть оператор класса Bar. Итак, вам нужно собрать ограничения, например, «a - некоторое неопределенное число или строка» и т. Д., А поскольку инструмент собирает доказательства, он сужает набор возможных ограничений. (Это работает так, как эти проблемы с текстом: «У Джо семь сыновей. Джефф выше Сэма, Гарри не может спрятаться за Сэмом ... который является близнецом Джеффа?», Где вам нужно собрать доказательства и снять невозможность). Вам также нужно беспокоиться о том, в каком случае вы столкнетесь с противоречием.
Вы можете исключить случай p.a + p.b, но тогда вы не можете писать свои юнит-тесты безнаказанно. Там есть стандартные ограничители, если вы хотите безнаказанности. (Какая концепция).
ОК, у нас есть идеи, теперь это можно сделать на практике?
Для первой части этого требуется анализатор и сгибаемое имя и тип распознавателя. Вам нужен решатель ограничений или, по крайней мере, операция «определенное значение потоков для неопределенного значения» (тривиальный решатель ограничений).
Возможно, наш DMS Software Reengineering Toolkit с его Java Front End может это сделать. DMS - инструмент инструментального инструментария для людей, которые хотят создавать инструменты, которые обрабатывают компьютерные языки произвольными способами. (Подумайте о «вычислениях с фрагментами программы, а не цифрами»).
DMS предоставляет универсальные синтаксические машины и может строить дерево для любого внешнего интерфейса (например, Java, а также переднего конца C#). Причина, по которой я выбрал Java, заключается в том, что на нашем интерфейсе Java есть все, что называется машиной разрешения имен и типов, и она предоставляется в исходной форме, поэтому ее можно согнуть. Если вы столкнулись с тривиальным решателем ограничений, вы, вероятно, можете сгибать распознаватель имен Java, чтобы выяснить типы. DMS позволит вам собирать деревья, соответствующие фрагментам кода, и объединять их в более крупные; поскольку ваш инструмент собирал факты для таблицы символов, он мог бы построить примитивные деревья.
Где-то вы должны решить, что все готово. Сколько единичных тестов инструмент должен видеть , прежде чем он узнает весь интерфейс? (Думаю, он ест все, что вы предоставляете?). После завершения сборки он собирает фрагменты для различных элементов и создает AST для интерфейса; DMS может использовать свой симпатичный принтер для преобразования этого АСТ обратно в исходный код, как вы показали.
Я предлагаю Java здесь, потому что наш интерфейс Java имеет разрешение имени и типа. Наш C# передний конец этого не делает. Это «простой» вопрос амбиций; кто-то должен написать один, но это довольно много работы (по крайней мере, для Java, и я не могу себе представить, что C# действительно отличается).
Но идея прекрасно работает в принципе с использованием DMS.
Вы можете сделать это с помощью какой-либо другой инфраструктуры, которая предоставила вам доступ к синтаксическому анализатору и сгибаемому имени и типу распознавателя. Это может быть не так легко получить для C#; Я подозреваю, что MS может дать вам синтаксический анализатор и доступ к разрешению имен и типов, но никак не изменить его. Может быть, Моно - это ответ?
Вам все еще нужно было сгенерировать фрагменты кода и собрать их. Вы можете попытаться сделать это путем хакерства строк; мой (длинный) опыт с склеиванием программных битов заключается в том, что, если вы делаете это со строками, вы в конечном итоге создадите беспорядок. Вам действительно нужны куски, которые представляют фрагменты кода известного типа, которые можно комбинировать только способами, которыми позволяет грамматика; DMS делает это, таким образом, беспорядок.
Вы можете сделать это с помощью шаблона [T4.] (Http://msdn.microsoft.com/en-us/library/bb126445.aspx) У меня нет образца, который удобен, но я мог бы попробовать написать один, если вам интересно. Я мог видеть, как это может быть действительно полезно при разработке Test-First (TDD); трюк заключается в том, что ваш код компилируется во время написания тестов для методов, которые еще не существуют. Другая проблема, конечно, в том, что шаблон T4, вероятно, должен быть более умным, чем то, что вы описали, и я сомневаюсь, что вы предоставили полную спецификацию в своем примере. – 2012-04-03 20:42:30
@RobertHarvey, я обсуждал это с коллегой, и у него создается впечатление, что может быть слишком много выводов. Я был бы просто доволен тем, что работает значительно умнее, чем текущее безумие «правого клика» :-) – Sklivvz 2012-04-03 20:53:04