CodeRainbow: інтерактивне вивчення і документування коду
Часто програмістам доводиться розбиратися з чужим незнайомим кодом. Це може бути і вивчення цікавих проектів з відкритим кодом, і необхідність по роботі — у разі приєднання до нового проекту, при аналізі великого обсягу legacy коду і т. д. Думаю, кожен з вас стикався з цим.
У мене в процесі такої роботи завжди гостро відчувалася необхідність якогось інструменту, спеціально заточеного для полегшення процесу швидкого занурення у великі обсяги незнайомого коду. З часом з’являлися нові цікаві задумки в різних областях, і всі вони вимагали вивчення великих обсягів чужого коду. Децентралізовані мережі, кріптовалюти, компілятори, операційні системи — все це великі проекти, що вимагають вивчення значних обсягів коду. В якийсь момент я вирішив: треба просто взяти і зробити цей спеціальний інструмент. У цій статті я представляю вашій увазі те, що вийшло в результаті.
Що взагалі може допомогти у вивченні коду? Звичайно, добре коли на код є докладна документація — це, як правило, її немає; хороший стиль кодування і коментарі це теж добре, але цього як правило недостатньо. Також існують різні генератори документації до коду, такі як doxygen. Аналізуючи структуру коду і спеціальні документирующие коментарі, що вони генерують документацію у вигляді гіпертексту html. Основний недолік такої документації — її неинтерактивность; у процесі вивчення коду у програміста може виникнути якесь нове розуміння, і для того щоб відобразити його в документації, потрібно написати нові документирующие коментарі і перегенерувати всю документацію заново.
Крім того, така документація не має безпосереднього зв’язку з кодом в середовищі розробки, тобто за клацанні на гіперпосиланні не відбудеться відкриття файлу з даними кодом IDE. Для таких інструментів є хороша аналогія, що йде корінням у стародавні часи: перші дізассемблер були інструментами командного рядка, які генерували код без участі користувача. Потім з’явився перший інтерактивний дізассемблер («IDA pro»), який передбачав активну участь користувача в процесі дизассемблирования — призначення імен змінних і функцій, визначення структур, написання коментарів до коду і т. д.
Аналіз великих обсягів чужого коду на высокоуровневом мовою в чомусь дуже схожий на дизасемблювання. Таким чином у мене почало складатися уявлення про те, що саме я хочу. У більшості IDE є класичні панелі File View і Class View, що відображають структуру файлів і просторів імен/класів всередині них. Але ця структура як правило жорстко пов’язана з синтаксисом мови і не дозволяє вносити користувача смислове навантаження. Таким чином, перше, що хотілося мати — це інтерактивна можливість побудови довільних дерев, що містять осмислено названі посилання на код — на ті ж класи та функції, або зовсім на довільні місця. І друге — це бажання якось позначити код безпосередньо в редакторі. Позначки можуть нести різний смисл: від простих «вивчено», «розібратися», «переписати», до належності коду до різним смисловим групам. Можна позначити коментарем, але хотілося чогось більш помітної. Наприклад, зміни кольору фону у фрагмента коду. Так що цветовыделители на КДПВ це досить точна аналогія з реального світу.
Провівши перші експерименти, я досить швидко зрозумів, що це повинен бути плагін до сучасної середовищі розробки, а не власний редактор. Працювати з двох редакторів одночасно — це нерозумно і незручно; перспектива повторювати всі можливості середовища розробки радості не викликала, та й навіщо робити те що вже зроблено? Тому плагін. Qt Creator був обраний в якості першої IDE просто тому, що в ньому найбільш затребувані операції навігації за кодом (Go to definition, Find references і т. д.) виконуються максимально швидко. Наступного середовищем буде Visual Studio, а далі — в разі успіху самої концепції реалізації для інших IDE.
Тепер про те, як воно все влаштовано. Введено поняття «маркерних коментарів». Це звичайний коментар мови програмування (в даний момент це однорядковий коментар “//”, який використовується в безлічі мов — C, C++, C#, Java,…), за яким слідує послідовність спецсимволов, після якої — ідентифікатор та/або позначки, за якими може розміщуватися звичайний людський коментар. Я ввів три типи маркерних коментарів
- Коментар для виділення довільної області (area). Єдиний тип, що вимагає «закриває» маркерного коментаря. Починається з “//<<” і закінчується “//>>”.
- Коментар для позначення довільного рядка в коді. Позначається “//$$”
- Коментар для виділення синтаксично правильного блоку коду. Починається з “//@@” і включає в себе розташований нижче блок коду, обмежений фігурними дужками “{” і “}”, які використовуються для блоків коду в більшості сі-подібних мов програмування. Реалізований повноцінний скобочный аналіз — допускаються вкладені фігурні дужки, також парсер коректно пропускає фігурні дужки в рядках і коментарях.
Далі, безпосередньо за спецсимволів слід один або декілька ідентифікаторів, розділених комами. Ідентифікатори є «тегами» і можуть означати те, що захоче програміст — ознаки «вивчено», «переписати», «розібратися», авторство коду, ставлення коду до якихось значеннєвих груп і т. д. Можна задати також один унікальний ідентифікатор — він ставиться першим і відділяється від інших двокрапкою. При бажанні можна явно вказати колір фону фрагмента коду — в кінці списку тегів ставиться решітка, після якої вказується колір у форматі RGB (хоча цей спосіб не найкращий — далі буде розказано про іншому, більш «правильний» спосіб). А в самому кінці можна поставити пробіл, після можна писати звичайний человекочитаемый коментар. Я намагався вибирати синтаксис таким чином, щоб він був максимально простим для швидкого введення, не захаращував код і був зручним і для звичайного коментування.
Хоча ручне введення маркерних коментарів і можливий, передбачається використовувати для цього спеціальні кнопки панелі інструментів. Курсор встановлюється в потрібну позицію коду і натискається кнопка (або з меню вибирається один з останніх варіантів).
При необхідності буде відкритий діалог вводу, куди можна ввести теги і ідентифікатори маркерних коментарів, докладний опис, а також вибрати колір фону. Ці дані будуть занесені не тільки код, але і в дерево «CRContentTree», коротке збоку панелі дерев (там де FileView, ClassView і т. д). Потрібно зазначити, що колір фону може бути «прозорим» — в цьому випадку використовується колір фону охоплюючого блоку (якщо такий є) або підсвічування взагалі не використовується.
На даний момент дерево складається з трьох основних частин (вузлів верхнього рівня): FILES, TAGS NOTES (можливо, це не остаточне рішення, т. к. концепція поки не цілком очевидна, як і зручність такої структури).
FILES — це файлова структура проекту, яка витягується з файлу проекту або з розміщення джерельних файлів на диску. Файлові вузли створюються при початковій генерації дерева. Подвійний клацання на файловому сайті звично відкриває файл у редакторі IDE. Можна вказати додавання маркерного коментаря в FILES — тоді дочірній вузол з’явиться у відповідного файлу. Саме сюди додаються унікальні ідентифікатори маркерних коментарів. Система перевіряє унікальність ідентифікації в межах файлового вузла дерева і дає можливість згенерувати унікальне ім’я автоматично.
TAGS — це глобальне хмара тегів проекту; теги не прив’язані до файлу вихідного коду і можуть зустрічатися в будь-якому файлі проекту скільки завгодно разів.
NOTES — це місце для зберігання вузлів, згрупованих довільним чином і не прив’язаних до файловій структурі. Кожен вузол містить шлях до файлу, і ідентифікатор. Основне призначення — створення користувальницьких логічних груп. Наприклад, «усі функції які потрібно переписати» або «всі функції, що мають відношення до криптографії», або «послідовність функцій мережного обміну з сервером» (оскільки вузли в дереві упорядковані, то просто розташовуючи вузли один за одним, можна відображати будь-які послідовності).
У кожного вузла дерева є контекстне меню. Вузол можна видалити (правда при цьому не проводиться видалення маркерних коментарів з коду — поки я не впевнений що це потрібно), можна відредагувати. Передбачено додавання вузлів, не пов’язаних з маркерними коментарями: можна додати наприклад посилання (Link). Подвійний клацання на такому сайті відкриє пов’язаний ресурс асоційованої програми, наприклад гіперпосилання в браузері.
Кожен вузол можна вимкнути, знявши відповідну галочку в чекбоксі сайту. Це призведе до того що підсвічування цього сайту та всіх дочірніх вузлів в коді буде знята. Таким чином, знявши наприклад галочки з трьох кореневих вузлів (FILES, TAGS NOTES) можна відключити підсвічування всіх маркерних коментарів, крім тих, у яких колір вказаний явно в коді (через ґрати).
Подвійний клацання на сайті відкриває відповідний файл в IDE і позиціонує курсор на відповідну позицію коду. Для тегів, які можуть зустрічатися багаторазово, замість відкриття файлу формується список всіх входжень, який завантажується в панель «CR Output», і вже подвійним клацанням на відповідній рядку цього списку можна відкрити файл і позицію в коді.
Кожен вузол має поле для докладного опису (багаторядковий текст довільної довжини). Це опис завантажується в область «CR Info» при простому виділення вузла у дереві (одинарним клацанням миші), а також встановивши курсор у будь-яке місце підсвіченої області в коді і натиснувши кнопку «Пошук» на панелі інструментів. Завжди доступно редагування, змінений текст зберігається автоматично (по втраті фокуса). Я подумую про те, щоб зробити в цій області підтримку формату Markdown, але поки руки до цього не дійшли.
Не завжди хочеться (або не завжди зручно) вставляти які-небудь коментарі в код. Тому друга можливість — «сигнатури», тобто використання в якості маркерів самого коду. Сигнатурою вважається деяка последовательрность токенів (без обліку пробілів і переносів рядків — тобто «foo(1,2,3)» і «foo ( 1, 2, 3 )» це одне і те ж). Передбачено три типи підпису:
- блокові — підсвічується блок, який починається з сигнатури і включає послідовність коду, укладену в фігурні дужки.
- однорядкові — підсвічується вся рядок з сигнатурою
- символьні — підсвічується тільки послідовність сигнатури. Такі сигнатури зручно використовувати для виділення окремих імен змінних, функцій, класів.
Робота з сигнатурними блоками така ж, як і з маркерними. Точно також створюються вузли в дереві.
Якщо для маркерних вузлів ідентифікатор теги створювалися окремо, то для сигнатурних пропонується вказати, як саме ми хочемо розглядати сигнатуру — як ідентифікатор (прив’язаний до файлу) або як глобальний тег. Наприклад, для «імен» логічно використовувати саме режим тегів — тоді відповідне ім’я буде підсвічено в коді по всьому проекту.
Ще одна цікава можливість — побудова покриття коду. Спеціальна функція сканує код і визначає місця, не зазначені взагалі ніяк, і формує список таких місць у «CR Output». При цьому не враховуються порожні рядки і комменитарии, тобто в скануванні враховується тільки значний код. Подвійним клацанням на рядку списку можна перейти до цього місця в коді, та вивчивши його, зазначити тим чи іншим способом.
Трохи про формат зберігання бази. Власне у вихідному коді зберігаються тільки маркерні коментарі; вміст дерева зберігається в спеціальному xml-файлі з розширенням “.cr”. Явною прив’язки файлу бази до проектів немає, хоча при відкритті проекту робиться спроба відкрити cr-файл з таким же ім’ям, якщо раніше ніякої cr-файл не був завантажений.
Підведу підсумки. У загальному і цілому я реалізував майже все те що хотів. Концепція нова і незвична, і тому потрібен певний час і зворотний зв’язок від користувачів, щоб зрозуміти — що потрібно розвивати, а від чогось, можливо, і відмовитися. У спробі реалізувати якомога більше можливостей щось вийшло злегка переусложненным, що неминуче. Сам інтерфейс можливо ще не сформований і буде змінюватися. Але в цілому, здається, вийшло непогано.
Що в планах. Ця версія демонстраційна, багато в чому сира і не призначена для комерційного використання. У мене є мрія — зробити свій комерційний продукт, приносить нехай невеликий, але постійний дохід, достатній щоб зайнятися іншими цікавими проектами. Крім того, деякі речі не адаптовані для комерційного використання. Я уявляю як подібну систему адаптувати для багатокористувацького режиму, з урахуванням того, що код може правиться кількома людьми одночасно, що працюють через систему контролю версій. Також можливо переглянути в бік генерації звичної документації (html), можливо — інструментів для більш глибокої інтеграції з кодом (синтаксичний аналіз замість лексичного/скобочного, автоматичне отримання списків класів і методів і перетворення їх в вузли дерева). Зрозуміло потрібно виправлення багів (які все ще є) і поліпшення фіч. Ну і звичайно я чекаю ваших коментарів з ідеями і пропозиціями 🙂
На цьому поки все (хоча залишилися ще деякі дрібні штуки, про які я не згадав у статті — наприклад я вважав за потрібне додати таби, так як без них зовсім сумно — хоча для табів є кілька плагінів; також на панель інструментів виведені деякі основні команди Qt Creator, що не мають відношення до плагіну; і т. д.).
Посилання для скачування: https://www.dropbox.com/s/9iiw5x7elwy3tpe/CodeRainbow4.zip?dl=0
Системні вимоги: Windows, Qt Creator >= 4.5.1 зібраний MSVC2015 32bit (це стандартна збірка, яка розповсюджується на download.qt.io)
установка: розпакуйте архів і скопіюйте плагін в папку c:/Qt/Qt5.10.1/Tools/QtCreator/lib/qtcreator/plugins (це приклад для стандартного розміщення Qt, якщо у вас Qt встановлений інакше або інша версія — шлях буде іншим) та (пере)запустіть Qt Creator.