Intellisense для динамических языков - PullRequest
5 голосов
/ 07 января 2010

Я ищу различные подходы для поддержки некоторого уровня intellisense на динамически типизированном языке. Поскольку информация об интеллигентности основана на информации о типах, при ее реализации для динамических языков существуют определенные трудности.

Знаете ли вы какие-либо алгоритмы или методы для его реализации?

Ответы [ 4 ]

7 голосов
/ 07 января 2010

Вам нужно написать абстрактный интерпретатор , который выполняет код со значениями типа. Таким образом, вы переходите к своему абстрактному интерпретатору через AST и записываете для каждой переменной отправленные сообщения или известные типы. И когда вы закончите, вы сделаете вывод о возможных типах, используя структурную эквивалентность типов (так называемый тип утки).

PS: в дополнение к выводу типов вы можете взглянуть на «Как история программы может улучшить завершение кода» Ромена Роббса , объясняет, как дальнейшее улучшение автозаполнения в динамических языках с помощью недавно использованной информации и совместной фильтрации.

Так вот как работает абстрактная интерпретация для фрагмента кода, подобного

def groups(array,&block)
  groups = Hash.new
  array.each { |ea| 
    key = block.call(ea)
    groups[key] = [] unless groups.include? key
    groups[key] << ea
  }
  return groups
end

вы бы начали с

array = { :messages => [], :types => [] }
block = { :messages => [], :types => [] }

, а затем

array = { :messages => [], :types => [] }
block = { :messages => [], :types => [] }
groups = { :messages => [], :types => [Hash] }

, а затем

array = { :messages => [:each], :types => [] }
block = { :messages => [], :types => [] }
groups = { :messages => [], :types => [Hash] }

, а затем

array = { :messages => [:each], :types => [] }
block = { :messages => [:call], :types => [] }
groups = { :messages => [], :types => [Hash] }
key = {  :messages => [], :types => [] }

, а затем

array = { :messages => [:each], :types => [] }
block = { :messages => [:call], :types => [] }
groups = { :messages => [:include?,:[]], :types => [Hash] }
group_elements = { :messages => [], :types => [Array] }
key = { :messages => [], :types => [] }

, а затем

array = { :messages => [:each], :types => [] }
block = { :messages => [:call], :types => [] }
groups = { :messages => [:include?,:[]], :types => [Hash] }
group_elements = { :messages => [:<<], :types => [Array] }
key = { :messages => [], :types => [] }

так что в итоге мы можем сделать вывод, что

  • array возможно Enumerable
  • block возможно Proc
  • groups - это Hash с Array элементами
  • key - это любой объект
1 голос
/ 07 января 2010

Я бы скачал исходные коды плагина Groovy для eclipse, он имеет intellisense (насколько это возможно), и думаю, что Groovy - хороший пример дианамического языка с динамической типизацией

0 голосов
/ 07 января 2010

Обратите внимание, что "динамический язык" и "динамически типизированный язык" не обязательно одно и то же.

Способ, которым Microsoft обрабатывает это в intellisense для Javascript (VS2008), заключается в том, что он делает все возможное, чтобы определить, какой тип хранится в настоящее время. Если / когда это изменится, следующие ссылки на var представят опции для обновленного типа.

0 голосов
/ 07 января 2010

Легко, нужно добавить только один дополнительный шаг - вывод типа .После этого вы знаете информацию о типе и можете предложить что-то пользователю.

...