Так сколько же берет написать движок IntelliSense

Разговоры на любые темы: вы можете обсудить здесь какой-либо сайт, найти единомышленников или просто пообщаться...
Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Так сколько же берет написать движок IntelliSense

Сообщение Хакер » 08.03.2012 (Чт) 4:25

Блин, это провал. Как только глянул твою квартинку, так сразу понял — провал. Значит я объяснил плохо. Потому что нарисована ерунда: к одному слову посреди строки проведена стрелка и подписано Affect Range.

Одно слова никак не может быть Affect-Rang'ем. Это раз.
Сколько угодно слов не может быть Affect-Range'ем, если каретка не в нём. А у тебя — не в нём.

Насколько я понял, ты ошибочно понимаешь смысл фразы «Affect-Range'е» как то так: affect-range — это что-то в коде, на суть чего влияет какая-то правка. Вот у тебя в коде факт закоментированности строки влияет на то, именем класса или именем переменной будет являеться идентификатор «Value» в коде. Я понял твою ошибку.

Ещё раз. Это совсем не то.
Представь себе контрол TextBox.
У него есть событие Change. В нём можно написать какую-то обработку.
У него есть событие Validate. В нём можно написать обработку, которая проверит правильность.
Событие change происходит абсолютно при каждой правке.
Событие Validate происходит, когда фокус покидает контрол.

А теперь представь себе такой TextBox, в котором события Change и Validate объедини в одно событие. И происходит оно не после каждой написанной/стёртой буквы, а после того, как пользователь осуществил редактирование достаточно большого блока. Вот этот блок и есть Affect-Range.

Affect-Range — это множество символов, токенная принадлежность которых может поменяться в результате редактирования. Например, они были частью строки, станут частью идентификатора. Были частью идентификатора, станут частью коментария. И т.п.

Affect-Range — это не множество символов, являющихся частями токенов, отождествляющих идентификаторы, суть которых (идентификаторов) может поменяться после редактирования какого-то блока.

Твоя ключевая ошибка в понимании меня хорошо видна в этом вопрос:
Qwertiy писал(а):В какой момент должно быть обработано изменение значения слова?

Изменение значения слов — это малозначимая (я знаю, будешь рьяно протестовать) задача. По крайней мере она очень вторична по сравнению с задачей определения «где здесь вообще что», то есть определения того, где начинается и заканчиваются идентификаторы, комментарии, строки, числа и т.п.

Qwertiy писал(а):Замечу кстати, что VB6 не подсвечивает имена классов.

Во-первых, какой смысл их подсвечивать, если единственное место, где могут появиться имена классов, это после ключевого слова New?
Во-вторых, VB хранить информацию о синтаксических структурах, имеющихся в коде, но не о связях сущностей и действий.

Например строку gva = 42 хранят не как информацию о том, что переменной gva присваивается значение 42, а как информацию о том, что чему-то с именем «gva» присваивают значение 42. VB принципиально, намеренно не хранит и не ведёт учёт того, что как с чем связано, потому что он должен уметь хранить в том числе и представление напрочь неправильного кода с помощью дерева. И он должен уметь показывать IntelliSense, в тех обстоятельствах, когда код неправилен.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Proxy
Профессор VB наук
Профессор VB наук
Аватара пользователя
 
Сообщения: 2941
Зарегистрирован: 31.08.2007 (Пт) 4:41

Re: Так сколько же берет написать движок IntelliSense

Сообщение Proxy » 08.03.2012 (Чт) 9:46

Хакер писал(а):Например строку gva = 42 хранят не как информацию о том, что переменной gva присваивается значение 42, а как информацию о том, что чему-то с именем «gva» присваивают значение 42.

А при использовании Option Explicit как устанавливается была ли объявлена переменная где-либо? Ищет каждый раз по всему графу (от данной вершины к корню)?
Follow the white rabbit.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Так сколько же берет написать движок IntelliSense

Сообщение Хакер » 08.03.2012 (Чт) 10:03

Proxy писал(а):А при использовании Option Explicit как устанавливается была ли объявлена переменная где-либо?

Всё-таки порядок вещей немного не такой. Неправильно думать, что если Option Explicit есть, то проводится проверка, а если Option Explicit нет — то не проводится.

Делается так: движок встречает элемент «присвоение чему-то с именем «gva» значения 42». Встретил. Пытается определить, что же такое gva. Смотрит, было ли что-то такое объявлено.
Если нет, и Option Explicit не включен — объявляет сам в соответствии с DefTpn-директивой.
Если нет, и Option Explicit включен — сообщает об ошибке.

Хочу обратить внимание на то, что есть две разных вещи.
«Информация об объявленных переменных» — ею пользуется IntelliSense, и она строится непосредственно при внесении правок в код.
«Информация о переменных, которые были объявлены в данный момент» — она строится при компиляции на основе первой информации, и ею пользуются при выбрасывании ошибки «Variable not defined».

Например, если написать
Код: Выделить всё
Sub foo
    bar = 7
End Sub


То IntelliSense не покажет переменную. Потому что нет информации о наличии Dim-а. IntelliSense пользуется информацией о наличии Dim-а (-ов). То есть первым источником информации.
Но компилятор пользуется вторым источником информации. Когда он дойдёт до этого места, он либо добавит её во второй источник, либо заорёт (выбор поведения делается на основе Option Explicit).

Но если мы напишем
Код: Выделить всё
Sub foo
    bar = 8
    Dim bar as long
End Sub


То IntelliSense уже будет показывать переменную bar. Потому что IntelliSense полагается на информацию о наличии Dim-а (первый источник). С компилятором интернеснее.
Если Option Explicit не включен, то компилятор дойдёт до первого элемента, посмотрит, есть ли объявление для такой переменной (во втором источнике информации — набор сущностей, которые объявлены на данный момент), и добавит переменную в этот набор. Но когда он дойдёт до второго элемента (объявление переменной), он попытается добавить во вторичный источник информацию из первичного, и окажется, что она там уже есть. Получаем Duplicate declaration.

Если Option Explicit включен, то когда компилятор дойдёт до первого элемента, посмотрит, есть ли объявление, то как и в прошлый раз — получится, что во втором источнике информации данных о переменной нет.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 08.03.2012 (Чт) 12:23

Хакер писал(а):Блин, это провал. Как только глянул твою квартинку, так сразу понял — провал. Значит я объяснил плохо. Потому что нарисована ерунда: к одному слову посреди строки проведена стрелка и подписано Affect Range.

Нет, ты объяснил нормально. Это я нарисовал не то, что имел в виду. Кстати, после "Affect Range" там не просто так знак вопроса стоит.

Я имел в виду, что для IntelliSense'а сущностью является просто слово, а не та сущность, которую оно означает для компилятора. Отсюда следуют несколько побочных эффектов и ограничений:
1. IntelliSense не позволяет использовать переменные с именами, отличающимися только регистром:
Код: Выделить всё
Sub A()
  Dim Q As Integer
End Sub

Sub B()
  Dim q As Integer
End Sub
Для компилятора эти переменные различны, но для IntelliSense - нет.
2. Возможности подсветки ограничены, точнее, можно подсвечивать только то, что можно определить независимо от контекста: ключевые слова, числа, строки, комментарии. Подсвечивать что-то ещё без расширения зоны воздействия как минимум до всего блока нельзя. Как-то различить класс (при наличии статических методов) и переменную нельзя. Как-то пометить необъявленную переменную нельзя. По-разному раскрасить глобальные переменные, переменные класса и локальные переменные нельзя.
3. [Забыл, если вспомню, напишу отдельно.]

Хакер писал(а):VB принципиально, намеренно не хранит и не ведёт учёт того, что как с чем связано, потому что он должен уметь хранить в том числе и представление напрочь неправильного кода с помощью дерева. И он должен уметь показывать IntelliSense, в тех обстоятельствах, когда код неправилен.

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

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Так сколько же берет написать движок IntelliSense

Сообщение Хакер » 08.03.2012 (Чт) 15:10

Qwertiy писал(а):При желании в этих целях можно ставить некоторую метку Unknown на идентификаторы, но вот для известных было бы лучше (с точки зрения программиста-пользователя) знать, что это. Только вот это невозможно как раз из-за концепции областей воздействия.


Ну так:
Код: Выделить всё
Dim foo as long
Dim foo as string
Static foo(48741) as Printer


Чем является foo? Как знать. Среда не должна ломаться от неправильного кода.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 08.03.2012 (Чт) 19:43

Хакер писал(а):Чем является foo? Как знать. Среда не должна ломаться от неправильного кода.

Ну почему же ломаться? С точки зрения компилятора, корректным является только первое объявление, поэтому оно Long.

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Так сколько же берет написать движок IntelliSense

Сообщение VBTerminator » 09.03.2012 (Пт) 10:30

Вы уж меня извините, но я не могу смотреть на дитя автоматического перевода в первом посте, поэтому переведу сам, чтобы другие могли адекватно понять топикстартера.
Stack Overflow писал(а):
Так как же Microsoft сделала, как вы называете, Intellisense?

Я могу объяснить это на любом уровне, какой вы пожелаете, но у меня нет времени на что-то большее, чем краткое описание. Я объясню, как мы сделали его в Roslyn (фреймворк для создания расширений в MS Visual Studio - прим. пер.).

Сначала строится статическая модель потока токенов, способная эффективно представлять правки, коих будет великое множество.

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

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

Очевидно, следующим шагом будет создание грамматического анализатора C#. Помните, он должен анализировать некорректный код. Помимо этого, IntelliSense должна работать с нескомпилированными проектами. Так что следующим шагом необходимо добавить в грамматический анализатор возможность коррекции ошибок.

На данном этапе у вас есть парсер, эффективно обрабатывающий только изменившиеся части текста. Это означает, что вы можете работать в промежутках между нажатиями на клавиши. Я забыл упомянуть, что нам нужен механизм, не блокирующий работу пользовательского интерфейса на период больший, чем нужно для последовательного нажатия двух клавиш. Новая возможность C#5 "async/await" должна помочь с этим. Могу сказать по собственному опыту: будьте осторожны с анализом задач. Если вам "повезёт", вы попадёте в очередь в сотню отменённых заданий, а это крайне медленно.

После грамматического анализатора нам нужен анализатор семантический. Он должен правильно составлять пригодную для компиляции модель, если программа корректна, и отчёт об ошибках в иных случаях.

Я советую начать с проектирования высокоуровневого анализатора, используя уже знакомую нам статическую модель. Он должен работать с тем, что не является выражениями - объявлениями типов, директивами, пространствами имён, прототипами, конструкторами, деструкторами и тому подобным, то есть с тем, что образует костяк программы при генерации метаданных компилятором.

Метаданные! Я совсем о них забыл. Помимо прочего вам необходим обработчик метаданных. Очевидно, IntelliSense нужно создать на основе выражений, ссылающихся на типы в библиотеках. Я рекомендую использовать библиотеки совместно используемой инфраструктуры связи, но ни в коем случае не рефлексию. Так как мы работаем исключительно над IntelliSense (а точнее, читателем-обработчиком метаданных), нам не нужны метаданные писателя.

Предположим, что вы уже создали семантический анализатор. Теперь настал черёд анализатора выражений, определяющего типы выражений. Уделите должное внимание алгоритмам просмотра имён и определения перегруженных операторов. Определение типа методов может быть непредсказуемым, особенно в LINQ.

Когда вы все сделаете, движок IntelliSense должен стать простым. Осталось только опознать тип конструкции под курсором и вывести список с подходящими выражениями.
Последний раз редактировалось VBTerminator 09.03.2012 (Пт) 14:13, всего редактировалось 8 раз(а).

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 09.03.2012 (Пт) 11:33

VBTerminator писал(а):Вы уж меня извините, но я не могу смотреть на дитя автоматического перевода в первом посте, поэтому переведу сам, чтобы другие могли адекватно понять топикстартера.

Спасибо. Наконец-то я это прочитал :)

Пред.

Вернуться в Народный треп

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 45

    TopList