.. _Refactoring Scripts:

Refactoring Scripts
===================


In some situations - like porting code from a library to another, or when dealing with cross-project API refactoring - one has to perform several refactoring operations for many projects. DVT can help you automate such operations by providing scripted refactoring functionality. Refactoring scripts are XML files that describe a set of changes to be performed for a project (into source code, scripts or file/directory names). For instance, such a script can describe all the changes to be applied to a source base for migration between OVM and UVM libraries.

Writing a Refactoring Script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~



Below there is a thoroughly commented example script to illustrate the XML syntax used by the scripting engine.

XML header and DTD specification on the first lines.

.. code-block:: 

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE refactor-script PUBLIC "-//DVT//refactor-script" "refactor-script.dtd" >

Start of refactoring script content. The script name is displayed in visual controls.

.. code-block:: 

    <refactor-script version="1" name="My refactoring script">

You can specify *exceptions*, i.e. paths that will not be affected by the refactoring. Paths are absolute or relative to the project root. You can specify both files and folders. For a folder, all files in it and in all its subfolders will be skipped.

.. code-block:: 

    <exception kind="path" path="skipme"/>

It is advised to exclude sensitive project configuration files, for example:

.. code-block:: 

    <exception kind="path" path=".project"/>

Actual refactoring directives are called *items*. There are several kinds of items, differentiated by the *action* they perform.

When writing a script, one must be careful not to have item collisions: situations when the same piece of text is modified by more than one item. Here are examples that illustrate all the actions currently available in DVT.

**replace-in-text**: perform plain textual search & replace for all the text files in the project like source files, scripts etc. Note that the search string is case sensitive.

.. code-block:: 

    <item action="replace-in-text"
    search="ovm"
    replacement="uvm" />

**replace-in-file-name** and **replace-in-dir-name**: perform plain textual search & replace in the names of all files/folders within the project.

.. code-block:: 

   <item action="replace-in-file-name"
       search="ovm" replacement="uvm" />

   <item action="replace-in-dir-name"
       search="ovm"
       replacement="uvm" />

**rename** all occurrences of the specified element (declaration and usages).

The **element-full-name** uniquely identifies a SystemVerilog language element, and should be specified as follows:

-  for macros, the name of the macro preceded by a backtick, just like a macro call

        .. code-block:: 

            <item action="rename"
                element-full-name="`my_macro"
                newname="`my_macro_new_name"/>

-  for types, modules, methods, etc., the name of the element, preceded by the names of its enclosing elements, including the package (if it's the case)

        .. code-block:: 

           <item action="rename"
            element-full-name="my_pkg::my_class"
            newname="my_class_new_name"/>

Note that the **newname** is just the name of the element. Here are some more examples:

.. code-block:: 

   <item action="rename"
       element-full-name="my_library.my_module.my_task"
       newname="my_task_new_name"/>

   <item action="rename"
       element-full-name="outer_class.inner_class.my_function"
       newname="my_function_new_name"
       comment="XXX: API change. Function renamed from my_function to my_function_new_name."/>


In the last example, *outer_class* is not inside any package (it's in the global scope).

Also, you can optionally specify a comment that will be inserted on the line above the occurence. If the comment contains a :ref:`Reminders (TODO Markers)` (like **TODO**, **FIXME**, **XXX** or a custom defined one), after refactoring is completed you can use the :ref:`Tasks View` to inspect action items or notes automatically added by the refactoring.

**add-comment**: to each occurrence of the specified element. The comment will be inserted on the line above the occurrence.

.. code-block:: 

    <item action="add-comment"
        element-full-name="my_type.foo"
        comment="FIXME: function removed from my_type API"/>

You can also specify whether you want to add comments only to the element **declaration** or only to its **usages**:

.. code-block:: 

   <item action="add-comment"
       apply-to="declaration"
       comment=" @deprecated API"
       element-full-name="my_class.deprecated_function" />
    

For **add-comment** items you can specify a set of elements that shall be affected by the refactoring (instead of specifying a single element via **element-full-name**) using a declaration comment pattern matcher and optionally a path matcher:

.. code-block:: 

   <item action="add-comment"
       comment=" FIXME: usage of deprecated ${element-signature}"
       apply-to="usages"
       element-comment-matches="*@deprecated*"
       element-path-matches="*/my_vip/*"/>

You can also use the **element-comment-matches-not** to invert the logic of the matcher.

Both **element-comment-matches** and **element-path-matches** perform simple pattern matching, that is * for any character sequence and ? for any character.

You can use **${element-signature}** in the comment, as shown in the example above: it shall be replaced with the element signature, as seen for example in tooltips.

Finally, the script closing tag.

.. code-block:: 
    
    </refactor-script>

To see a larger example, you can simply start the :ref:`OVM to UVM Migration` wizard and inspect the script behind it (there is an *Inspect* button on the right side of the first wizard page).

.. tip:: 

 **Right-click in the XML editor** > **Validate** to early detect syntax problems (requires the DTD specification line in the xml header).

.. tip:: 

 Use :kbd:`Ctrl+Space` to invoke **autocomplete** in the XML editor for tag and attribute names (requires the DTD specification line in the xml header).

Applying a Refactoring Script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



To apply a script, **right click on the script.xml** file and select **Refactor > Apply a refactoring script**. The refactoring wizard start automatically.
You can also **right click on project**, select **Refactor > Apply a refactoring script**, then browse to the script you want to apply.

.. figure:: ../../images/vlogdt-refactor-script-select.png



You can either apply the changes straightforward or inspect them in a *Preview* wizard page, where you can select which of the proposed changes should be performed. Also, on the top-right of the preview wizard you have a *Filter* button that allows you to filter changes by the type of refactoring action. To apply the refactoring, click *Finish*

.. figure:: ../../images/vlogdt-refactor-script-refactoring.png



#.  Select a file/change to see the source differences produced by the refactoring.
#.  Un-check a file/change to prevent those changes from being applied.
#.  Filter the displayed changes by type of refactoring item

.. tip:: 

 Add +dvt_ref_scripts_debug+true directive to your .dvt/default.build to see debug information about the script execution in the DVT Build Console



