-
Устанавливаю пакеты
npm i
, запускаю по F5 дебаг. VS Code сообщает о 2 ошибках в файлеserver.ts
:-
Argument of type '(params: InitializeParams) => { capabilities: { textDocumentSync: string; }; }' is not assignable to parameter of type 'RequestHandler<InitializeParams, InitializeResult, InitializeError>'. Types of property 'textDocumentSync' are incompatible. Type 'string' is not assignable to type '0 | TextDocumentSyncOptions | 1 | 2 | undefined'.
Жму F12 на
textDocumentSync
и нахожу описание типа в котором указано, что значение1
соответствует полной синхронизации документа и сервера. Устанавливаю пока это значение. -
Property 'loc' does not exist on type 'AstIdentifier'.
Опыт работы с библиотекой
json-to-ast
во втором задании подсказывает, что у интерфейсаAstIdentifier
забыли указать полеloc
. Исходники библиотеки лишь подтверждают это.
-
-
Запускаю дебаг, открываю вкладку Preview по Ctrl+Shift+V и вижу
{{content}}
. Похоже на какую-то проблему с шаблонизацией. Нахожу функциюupdateContent
в файлеextension.ts
и обращаю внимание наswitch
в котором один из кейсов равенcontent
. Ставлю брейкпоинты на всех выходах изswitch
, но дебагер не заходит в них. Думаю, может дебагер сломался. Перехожу к тяжелой артилерии и вставляюconsole.log(str);
передswitch
, а в дебаг консоли тишина. Тут я подвис и не понимал почему функция не выполняется. Полез на MDN смотреть документацию наString.replace()
. Оказалось функция запускается только при успешном сопоставлении. Значит проблема в регулярном выражении. Внимательно посмотрев на него, можно заметить, что там используется выражение\s+
, которое соответствуют одному или более пробельному символу. Меняю на\s*
, которое соответствуют нулю или более пробельному символу. Дебагер теперь ходит поswitch
и вpanel.webview.html
присваивается сгенерированный html. Вкладка Preview теперь пустая. -
Решил убедиться, что сгенерированный html добирается до Preview вкладки. Запускаю в VS Code команду Developer: Open Webview Developer Tools html добавляется, но в консоли замечаю ошибку
Failed to load resource: net::ERR_UNKNOWN_URL_SCHEME resource:/d%3A/Dev/Shri/shri-2020-3/preview/style.css
. Поиск по этой ошибки ничем мне не помог. Пробую закоментировать строку.with({ scheme: "resource"})
и получаю уже другую ошибкуNot allowed to load local resource
. Поиск по этой ошибке выводит меня на документацию по vscode webview, где глаз цепляется заvscode-resource
. Пробую эту схему. Ошибка пропадает, но вкладка Preview всё еще пустая. -
В Dev Tools начал смотреть стили блоков на Preview вкладке, а там только
div { display: block; }
. Оказалось в стилях указаны селекторы по классу, а не по типу элемента. Исправляю. Теперь на вкладке Preview что-то похожее на то, что изображено на скриншоте к заданию. -
Проверяю функционал по списку в задании - всё работает. нужно лишь добавить стили из первого задания.
-
Добавляю стили. Всё работает, темы переключаются, блоки перестраиваются при растягивании окна Preview.
-
Запускаю дебаг. Перевожу названия некоторых свойств в верхний регистр и ничего не происходит, никаких ошибок в консоль. Начинаю ставить брейкпоинты во всех методах и колбеках файла
server.ts
. Перезапускаю дебаг и ни один брейкпоинт не сработал. Начинаю расставлятьconsole.log()
вместо брейпоинтов. Снова тишина в DEBUG CONSOLE. Вспоминаю, что у линтера есть настройки. Захожу в настройки расширения и включаю линтер. Никакого эффекта. Начинаю смотреть документацию как правильно дебажить. Нахожу на этой странице ссылку на проектlsp-sample
и упоминание, что можно дебажить клиент и сервер одновременно. Изучаю launch.json того проекта. Добавляю конфигурацию для дебага сервера. Запускаю дебаг. Ошибки и консольлоги появились в DEBUG CONSOLE. -
Ставлю бейкпоинт на
Uncaught Exceptions
, меняю текст в документе и дебагер останавливается на строкеnode_modules\json-to-ast\build.js:1960:5
. Просмотрев call stack становится понятно, что на вход библиотекиjson-to-ast
подается адрес файла вместо его содержимого. Ошибка в строкеconst json = textDocument.uri;
функцииvalidateTextDocument
. Жму F12 на типеTextDocument
и нахожу методgetText(range?: Range): string;
, который должен возвращать текст документа. Исправляю. Ошибка пропадает. Проверяю дебагером - AST дерево генерируется. Линтер не выводит никаких ошибок, хотя в документе они есть. -
Начинаю дебажить функции
validateObject
иvalidateProperty
. Добираясь до элементов с ошибками они возвращают непустые массивы. Но в переменнуюerrors
объекты этих массивов не складывались. Виной всему функцияconcat
, которая создает новый массив, а не добавляет элементы в имеющийся. Меняю наpush
. Ошибки стали появляться на вкладке PROBLEMS. -
Проверяю работу линтера по пунктам из задания. Всё работает кроме переключения
Severity
правил:- При переключении в
Error
иконка ошибок меняется наInfo
, а не наError
. - Если оба правила переключить в
None
, то последнее переключенное правило остается висеть в ошибках.
Первый баг быстро нахожу в функции
GetSeverity
и исправляю. Для исправления второго дебажу функциюvalidateTextDocument
. Там получается, что при выключении правил массивdiagnostics
становится пустым и из-за условного оператора он не отправляется на клиент, поэтому там всегда остается ошибка. Пробую убрать условный оператор. Всё работает. - При переключении в
-
Проверяю как работает линтер при исправлении ошибок и замечаю, что он не убирает подсветку, если json не валиден и выкидывает исключения в OUTPUT. ESLint, например, убирает все ошибки и выводит только ошибку, связанную с местом, которое он не смог распарсить. Чтобы вывести такие ошибки в рамках данной архитектуры потребуется дописать лишний десяток строк, не думаю, что задание подразумевает внесение таких изменений, поэтому просто помещаю вызов библиотеки
json-to-ast
вtry{} catch{}
и возвращаюundefined
в случае ошибки парсинга, как делал это во втором задании. Теперь линтер выводит ошибки только для валидного json. Не знаю является ли это ошибкой, которую надо было найти, но как улучшение выглядит неплохо. -
После просмотра разборов заданий прошлых лет запомнил, что в заданиях на поиск ошибок добавляют мертвый код. Просмотрел весь исходный код и обнаружил что файлы
hash.ts
иjsonMain.ts
никуда не импортируются. Удалил файлы. Раширение работает без изменений. -
Навожу порядок в оформлении кода. Удаляю TSLint по причине:
TSLint will be deprecated some time in 2019.
Устанавливаю ESLint, Prettier. Настраиваю конфиг и переношу некоторые правила из
tslint.json
. Запускаюnpm run lint:fix
. Вручную исправляю оставшиеся ошибки. Удаляю неиспользуемые пакеты. -
Добавляю линтер из второго задания. Проверяю на тестовых данных второго задания. Ошибки выводятся. Настройки расширения работают.
-
Подчищаю
TODO
комментарии. Пока смотрел исходники примеров обратил внимание на эти строки иtextDocumentSync: documents.syncKind
. Подебажил иdocs.syncKind
действительно равен1
. Избавляюсь от магических цифр и устанавливаю значение как в примере.
Большинство ошибок можно было бы избежать с настроенным линтером и написанными тестами. Дополнительно можно pre-coomit hook
настроить, чтобы точно в репозиторий плохой код не попадал. Правда прогон тестов на хуке возможен, наверное, только на мелких проектах, но для крупных тоже что-нибудь можно сделать, например, pre-push
c запросом у CI сервера информации о пройденных тестах для данного хеша.
Для поиска неиспользуемых зависимостей я использовал утилиту depcheck. Особо не выбирал, первая строчка в поисковике, посмотрел лишь количество скачиваний и как давно обновлялась. В readme было написано, что может выдавать ложную информацию, поэтому все зарепорченые зависимости я проверил вручную.
Утилит для поиска мертвого кода я не нашел, в поисковиках информация лишь о tree shaking
в webpack и rollup. Единственное что приходит в голову это отключать все юнит тесты, прогонять e2e тесты и смотреть на code coverage. Но нулевое покрытие всё равно не дает никаких гарантий и нужно всё проверять руками.
Для поддержания единого кодстайла и форматирования в проекте я использовал ESLint и Prettier. Фронтендом занимаюсь с начала выполнения заданий в ШРИ и как понял эти утилиты что-то вроде стандарта индустрии, ну по крайней мере линтер. Поэтому выбором не занимался, просто взял и настроил.