= Gerrit Code Review - PolyGerrit Plugin Development CAUTION: Work in progress. Hard hat area. Please link:https://bugs.chromium.org/p/gerrit/issues/entry?template=PolyGerrit%20plugins[send feedback] if something's not right. [[migration]] == Incremental migration of existing GWT UI plugins link:pg-plugin-dev.html[PolyGerrit plugin API] operates different concepts and provides different type of API compared to ones available to GWT plugins. Depending on the plugin, it might require significant modifications to existing UI scripts to fully take advantage of benefits PolyGerrit API provides. To make migration easier, PolyGerrit recommends incremental migration strategy. Starting with a .js file that works for GWT UI, plugin author can incrementally migrate deprecated APIs to new plugin API. The goal for this guide is to provide migration path from .js-based UI script to .html-based. NOTE: Web UI plugins distributed as a single .js file are not covered in this guide. Let's start with a basic plugin that has an UI module. Commonly, file tree should look like this: ├── BUILD ├── LICENSE └── src └── main ├── java │   └── com │   └── foo │   └── SamplePluginModule.java └── resources └── static └── sampleplugin.js For simplicity's sake, let's assume SamplePluginModule.java has following content: ``` java public class SamplePluginModule extends AbstractModule { @Override protected void configure() { DynamicSet.bind(binder(), WebUiPlugin.class) .toInstance(new JavaScriptPlugin("sampleplugin.js")); } } ``` === Step 1: Create `sampleplugin.html` As a first step, create starter `sampleplugin.html` and include UI script in the module file. NOTE: GWT UI ignore .html since it's not supported. ``` java @Override protected void configure() { DynamicSet.bind(binder(), WebUiPlugin.class) .toInstance(new JavaScriptPlugin("sampleplugin.js")); DynamicSet.bind(binder(), WebUiPlugin.class) .toInstance(new JavaScriptPlugin("sampleplugin.html")); } ``` Here's recommended starter code for `sampleplugin.html`: NOTE: By specification, the `id` attribute of `dom-module` *must* contain a dash (-). ``` html ``` Here's how this works: - PolyGerrit detects migration scenario because UI scripts have same filename and different extensions * PolyGerrit will load `sampleplugin.html` and skip `sampleplugin.js` * PolyGerrit will reuse `plugin` (aka `self`) instance for `Gerrit.install()` callbacks - `sampleplugin.js` is loaded since it's referenced in `sampleplugin.html` - setup script tag code is executed before `sampleplugin.js` - cleanup script tag code is executed after `sampleplugin.js` - `plugin.deprecated.install()` enables deprecated APIs (onAction(), popup(), etc) before `sampleplugin.js` is loaded So the purpose is to share plugin instance between .html-based and .js-based code, making it possible to gradually and incrementally transfer code to new API. === Step 2: Create cut-off marker in `sampleplugin.js` Commonly, window.Polymer is being used to detect in GWT UI script if it's being executed inside PolyGerrit. This could be used to separate code that was already migrated to new APIs from the one that hasn't been migrated yet. During incremental migration, some of the UI code will be reimplemented using PolyGerrit plugin API. However, old code still could be required for the plugin to work in GWT UI. To handle this case, add following code to be the last thing in installation callback in `sampleplugin.js` ``` js Gerrit.install(function(self) { // Existing code here, not modified. if (window.Polymer) { return; } // Cut-off marker // Everything below was migrated to PolyGerrit plugin API. // Code below is still needed for the plugin to work in GWT UI. }); ``` === Step 3: Migrate! The code that uses deprecated APIs should be eventually rewritten using non-deprecated counterparts. Duplicated pieces could be kept under cut-off marker to work in GWT UI. If some data or functions needs to be shared between code in .html and .js, it could be stored on `plugin` (aka `self`) object that's shared between both === Step 4: Cleanup Once deprecated APIs are migrated, `sampleplugin.js` will only contain duplicated code that's required for GWT UI to work. With sudden but inevitable GWT code removal from Gerrit that file can be simply deleted, along with script tag loading it.