{"id":20505130,"url":"https://github.com/rabotaru/synthetic-migrate-plugin","last_synced_at":"2025-10-27T00:48:18.579Z","repository":{"id":97589353,"uuid":"481898048","full_name":"RabotaRu/synthetic-migrate-plugin","owner":"RabotaRu","description":"Плагин для Android Studio/Intelij IDEA с помощью которого можно мигрировать кодовую базу с котлиновской синтетики на view-binding","archived":false,"fork":false,"pushed_at":"2022-05-16T12:40:30.000Z","size":97,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-13T21:06:02.697Z","etag":null,"topics":["android-studio-plugin","idea-plugin","kotlin-syntetics","psi","view-binding"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RabotaRu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-15T08:54:33.000Z","updated_at":"2025-04-04T20:06:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"682592d4-5ac2-471e-87bb-bef8d586cbd0","html_url":"https://github.com/RabotaRu/synthetic-migrate-plugin","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/RabotaRu/synthetic-migrate-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RabotaRu%2Fsynthetic-migrate-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RabotaRu%2Fsynthetic-migrate-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RabotaRu%2Fsynthetic-migrate-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RabotaRu%2Fsynthetic-migrate-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RabotaRu","download_url":"https://codeload.github.com/RabotaRu/synthetic-migrate-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RabotaRu%2Fsynthetic-migrate-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272186211,"owners_count":24888333,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-26T02:00:07.904Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android-studio-plugin","idea-plugin","kotlin-syntetics","psi","view-binding"],"created_at":"2024-11-15T19:44:03.973Z","updated_at":"2025-10-27T00:48:13.559Z","avatar_url":"https://github.com/RabotaRu.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Synthetic Migrate Plugin\n\n## Описание\nПлагин для Android Studio/Intelij IDEA с помощью которого можно мигрировать кодовую базу с котлиновской синтетики на view-binding. \nПоддерживает Android Studio 4.1+ и Intelij IDEA 2020.1+ \n\n## Установка \n1. Скачать jar [из последнего релиза](https://github.com/RabotaRu/synthetic-migrate-plugin/releases/)\n2. Preferences -\u003e Plugins -\u003e Settings -\u003e Install Plugin From Disk \u003cimg width=\"640\" alt=\"Снимок экрана 2022-04-15 в 16 16 27\" src=\"https://user-images.githubusercontent.com/7330056/163575390-b1d815a6-7e73-487d-9076-d8dd81be4458.png\"\u003e\n3. Выбрать jar\n4. Перезагрузить студию \n5. Точка входа в плагин появится в верхнем меню \n\u003cimg width=\"175\" alt=\"Снимок экрана 2022-05-16 в 15 40 01\" src=\"https://user-images.githubusercontent.com/7330056/168594420-e4e2b9f9-2966-45af-b6b6-ddcdb0817534.png\"\u003e\n\n\n\n\n# Описание интерфейса\n\n## Первый таб - Миграция\n\n\u003cimg width=\"462\" alt=\"Снимок экрана 2022-04-15 в 16 34 13\" src=\"https://user-images.githubusercontent.com/7330056/163577085-d47d3d9e-c126-46cf-bf7d-96ebbed5ae81.png\"\u003e\n\n### Описание\nВ первом табе происходит настройка миграции, указание сущности которая будет мигрировать, то как будет инициализироваться view binding, где будет инициализироваться, указание доп импортов и т.д.\n\n**Чекбокс \"Локальная переменная\"** - если он установлен, то binding переменная будет создана в методе указанном в поле \"Метод инициализации\", так что после того как чекбокс становиться активным поле \"Метод инициализиации\" становиться обязательным\n\n**Поле \"Родительский класс\"** - это обязательное поле, которое заполняется именем родительского класса сущности которую нужно перевести на view binding. Например нам нужно перевести все сущности которые наследуются от Fragment, значит пишем там Fragment.\n\n**Поле \"Название базового класса\"** - поле в которе вводится название базового класса сущности. Например нужно перевести все фрагменты на view binding, и есть базовый абстрактный класс BaseFragment, в котором переменная binding установленная абстрактной, следовательно нужно в каждом наследнике BaseFragment переопределять эту переменную. Значит указываем в Поле \"Родительский класс\" Fragment, в этом поле BaseFragment. И плагин везде где родитель BaseFragment - переопределит binding переменную(добавит override), а где только Fragment - создаст новую.\n\n**Поле \"Название binding переменной\"** - то как будет называться генерируемая переменная. По умолчания binding \n\n**Поле \"Метод инициализации\"** - поле которое нужно заполнить если необходимо инициализировать view binding переменную в каком то методе. Она используется как в связке с Чекбоксом \"Локальная переменная\", так и без него.\n1. Если выбран чекбокс и заполнено это поле, то переменная будет создана исключительно в в том методе, который указан в поле\n2. Чекбокс не выбран и заполнено поле, будет создана глобальная переменная с lateinit и инициализирована в методе который указан в этом поле\n\n**Поле \"Шаблон инициализации\"** - поле в котором прописывается то как будет инициализирована переменная. Т.к. инициализация сопрежена с обращения к, сгенерированным view binding плагином, классами, то в этом поле можно указать \u003ctype\u003e, где \u003ctype\u003e это сгенерированный view binding класс, для обрабатываемого класса. Например есть делегат, с помощью которого нужно инициализировать во всех фрагментах binding. Для Фрагмента с лэйаутом R.layout.fragment_search эта инициализация должно выглядеть так val binding by fragmentBindingDelegate(FragmentSearchViewBinding::bind). Значит нужно вписать в это поле by fragmentBindingDelegate(\u003ctype\u003e::bind). И тогда в каждом фрагменте, где плагин сможет найти лэйаут будет подставлен класс сгенеренный на основе этого лэйаута. \n\n**Поле \"Необходимы импорты\"** - плагин по умолчанию удаляет все импорты с синтетикой и добавляет импорты с view binding. На иногда необходимы еще некоторые импорты, например когда используешь тот же делегат для инициализации. Например: ru.rabota.app2.delegate.viewbinding и тогда в списке импортов у каждого обработанного файла появится import ru.rabota.app2.delegate.viewbinding. Это поле так же имеет правило: один импорт - одна строка \n\n**Кнопка \"Мигрировать\"** - запускает процесс генерации переменной и замены импортов. После нажатия все повиснет и это нормально. После выполнения миграции появится диалог о завершении\n\n**Кнопка \"Сбросить\"** - сбрасывает все настройки и очищает поля в этом табе\n\n**Кнопка \"Отмена\"** - закрывает диалог\n\n  \n## Второй таб - Замена родительского класса\n  \n\u003cimg width=\"462\" alt=\"Снимок экрана 2022-04-15 в 16 38 02\" src=\"https://user-images.githubusercontent.com/7330056/163577445-74a4e3d2-3cde-4415-a856-c7d6f5b09e66.png\"\u003e\n  \n### Описание\n  \nВторой таб позволяет заменять родительские классы. Это необходимо если во время переезда на view-binding в родительском классе добавился новый generic и чтобы во всех наследуемых классах руками его не добавлять может пригодится эта фича.\n\n**Поле \"Что заменяем\"** - в этом поле указывается класс от которого наследуются и который изменился/заменился. Например у был класс BaseFragment\u003cViewModel\u003e и стал BaseFragment\u003cViewBinding, ViewModel\u003e и везде нужно подставить этот ViewBinding. Значит в этом поле указывается имя такого класса который необходимо заменить т.е. BaseFragment\n\n**Поле \"На что заменяем\"** - в этом поле указывается выражение на которое заменяется класс указанный выше. Это поле имеет 2 особенности: \n1. Когда заменяем BaseFragment\u003cViewModel\u003e на BaseFragment\u003cViewBinding, ViewModel\u003e, нужно добавить view binding класс и сохранить имеющуюся уже там  viewmodel  класс. И тут нам на помощь приходит \u003ctype\u003e \u0026 \u003cindex\u003e, где type аналогичен type из шаблона инициализации, а \u003cindex\u003e, где index это индекс generic'а, начиная с 0. \nВ этом примере в поле будет записано BaseFragment\u003c\u003ctype\u003e, \u003c0\u003e\u003e. Где \u003c0\u003e -  это ViewModel\n2. Так же много где есть аргументы в первичном конструкторе, для того что бы они не исчезли при замене указывается [index] - где index это индекс аргумента, начиная с 0. Например есть BaseItem(abs, test), заменить на SuperItemBase\u003cViewBinding\u003e(abs, test). Значит в этом поле нужно указать SuperItemBase\u003c\u003ctype\u003e\u003e([0],[1])\n\n**Поле \"Необходимый импорт\"** - импорт который добавляется в процессе замены в каждый обработанный файл. Например: ru.rabota.app2.delegate.viewbinding и тогда в списке импортов у каждого обработанного файла появится import ru.rabota.app2.delegate.viewbinding\n\n**Кнопка \"Заменить\"** - запускает процесс замены \n\n**Кнопка \"Очистить\"** - очищает поля\n\n  \n# Примеры использования \n  \n## Миграция фрагментов\n  \n\u003cimg width=\"462\" alt=\"Снимок экрана 2022-04-15 в 16 43 29\" src=\"https://user-images.githubusercontent.com/7330056/163578064-6a5e748e-2d2e-4133-b3b0-bca3a3f9b995.png\"\u003e\nЗдесь во всех фрагментах сгенерится переменная с именем binding, а в тех кто наследовался от BaseFragment переменная биндинг будет override. Инициализация будет такая binding by someDelegate(NameViewBinding::bind). И в каждый обработанный файл добавиться импорт ru.rabota.app2.delegate.someDelegate. И у всех вьюшек в каждом классе вначале появится binding.\n  \n## Миграция итемов списка\n  \n\u003cimg width=\"462\" alt=\"Снимок экрана 2022-04-15 в 16 45 19\" src=\"https://user-images.githubusercontent.com/7330056/163578280-30e4c350-6cc7-4ce5-a6d6-a93e2754c817.png\"\u003e\n  На данном скриншоте приведен пример миграции итема списка. Т.е. во всех классах с родителем Item, в методе onBind будет сгенерирована переменная с названием itemBinding и инициализирована так: itemBinding = NameViewBinding.bind(viewHolder.itemView)\n\n## Добавления во всех наследованиях нового дженерика \n  \n\u003cimg width=\"462\" alt=\"Снимок экрана 2022-04-15 в 16 47 13\" src=\"https://user-images.githubusercontent.com/7330056/163578497-57b6130d-f579-4721-ace3-5de33b251404.png\"\u003e\nВ этом примере во все наследования от BaseFragment будет добавлен generic c типом биндинга который был найден в классе. Например: \nбыло MainFragment: BaseFragment\u003cMainViewModel\u003e()\nстанет MainFragment: BaseFragment\u003cMainViewModel, MainFragmentBinding\u003e()\nИ так же во всех классах которые наследуются от BaseFragment, первый дженерик сохранится за счет того что было прописано \u003c0\u003e, и добавится новый с типом биндинга за счет добавления \u003ctype\u003e\n  \n## Добавления во всех наследованиях нового аргумента\n  \n\u003cimg width=\"462\" alt=\"Снимок экрана 2022-04-15 в 16 51 49\" src=\"https://user-images.githubusercontent.com/7330056/163579035-5372270d-8d5d-4726-83c7-9ed5ede2b9f3.png\"\u003e\nВ этом примере происходит замена наследования с добавлением нового аргумента и сохранением старого. Например:\nбыло MainItem(orientation: Int, data: Int): BaseItem(orientation)\nстанет MainItem(orientation: Int, data: Int): BaseItem(orientation, data)\nИ так же во всех классах которые наследуются от BaseItem, первый аргумент сохранится за счет того что было прописано [0], и добавится новый за счет добавления data\n  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frabotaru%2Fsynthetic-migrate-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frabotaru%2Fsynthetic-migrate-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frabotaru%2Fsynthetic-migrate-plugin/lists"}