{"id":7517,"date":"2021-10-26T11:04:01","date_gmt":"2021-10-26T18:04:01","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=7517"},"modified":"2021-10-26T13:09:40","modified_gmt":"2021-10-26T20:09:40","slug":"refactorscript-language-description","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/documentation\/refactorscript\/language\/","title":{"rendered":"RefactorScript Language Description"},"content":{"rendered":"<p>This page provides an overview of the RefactorScript language used by VisualGDB to define custom code generation patterns.<\/p>\n<h2>Contents<\/h2>\n<p><a href=\"#overview\">Overview<\/a><br \/>\n<a href=\"#output\">Output<\/a><br \/>\n<a href=\"#expressions\">Expression Substitution<\/a><br \/>\n<a href=\"#statements\">Statements<\/a><br \/>\n<a href=\"#set\">set<\/a><br \/>\n<a href=\"#foreach\">foreach<\/a><br \/>\n<a href=\"#if\">if<\/a><br \/>\n<a href=\"#variables\">Variables<\/a><br \/>\n<a href=\"#functions\">Functions and Generators<\/a><br \/>\n<a href=\"#types\">Data Types<\/a><br \/>\n<a href=\"#string\">string<\/a><br \/>\n<a href=\"#array\">array<\/a><br \/>\n<a href=\"#args\">Main Generator Parameters<\/a><br \/>\n<a href=\"#attributes\">Attributes<\/a><\/p>\n<h2><a id=\"overview\"><\/a>Overview<\/h2>\n<p>The RefactorScript syntax is based on a simplified C# syntax. It is optimized for extremely fast execution, so you can typically preview the results of running your script directly as you type it.<\/p>\n<p>Each RefactorScript must contain at least one <strong>generator<\/strong> &#8211; a function that generates output. The simplest syntax for a generator is shown below:<\/p>\n<pre class=\"\">[Main]\r\ngenerator DemoGenerator(Function func)\r\n{\r\n}<\/pre>\n<p>Note that the <strong>[Main]<\/strong> attribute marks the entry point of the RefactorScript and is only needed if the script contains multiple generators.<\/p>\n<h2><a id=\"output\"><\/a>Output<\/h2>\n<p>Any line inside a generator that starts with &#8220;&gt;&#8221; will be directly translated to an output line. E.g. the following generator will just produce the &#8220;\/\/Hello, World&#8221; text:<\/p>\n<pre class=\"\">generator DemoGenerator(Function func)\r\n{\r\n&gt;\/\/Hello, World\r\n}<\/pre>\n<p>Lines starting with &#8220;&gt;&gt;&#8221; will be treated as incomplete (i.e. no newline will be inserted after them). E.g.:<\/p>\n<pre class=\"\">generator DemoGenerator(Function func)\r\n{\r\n&gt;&gt;\/\/Hello,\r\n&gt; World!\r\n&gt;\/\/Hello, Script!\r\n}<\/pre>\n<p>The generator above will produce the following output:<\/p>\n<pre class=\"\">\/\/Hello, World!\r\n\/\/Hello, Script!<\/pre>\n<h2><a id=\"expressions\"><\/a>Expression Substitution<\/h2>\n<p>The lines starting with &#8220;&gt;&#8221; and &#8220;&gt;&gt;&#8221; can use the &#8220;$&#8221; syntax to refer to expressions based on the generator parameters. E.g. the following script will output the name of the function passed to it:<\/p>\n<pre class=\"\">generator DemoGenerator(Function func)\r\n{\r\n&gt;\/\/Hello, $func.ShortName\r\n}<\/pre>\n<p>The expressions can include multiple levels of fields, but cannot include function calls, e.g.:<\/p>\n<table style=\"border-collapse: collapse; width: 100%;\" border=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 50%;\">Format<\/td>\n<td style=\"width: 50%;\">Result<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">\n<pre class=\"\">&gt;Hello, $func.Arguments.First.ShortName<\/pre>\n<\/td>\n<td style=\"width: 50%;\">\/\/Hello, argc<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">\n<pre class=\"\">&gt;Hello, $func.Arguments.First.ShortName.AddPrefix(\"m_\")<\/pre>\n<\/td>\n<td style=\"width: 50%;\">Error<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">\n<pre class=\"\">set tmp = func.Arguments.First.ShortName.AddPrefix(\"m_\");\r\n&gt;\/\/Hello, $tmp<\/pre>\n<\/td>\n<td style=\"width: 50%;\">\/\/Hello, m_argc<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The first input to the main generator always contains an object representing the C\/C++ entity that was selected when running the script. It contains exhaustive information about fields, methods, variables, types, typedefs, etc. You can find a detailed reference of the RefactorScript data model <a href=\"\/documentation\/refactorscript\/datamodel\">here<\/a>, or simply use the view on the right side of the RefactorScript window to explore it in real time:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/10\/demo1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7518\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/10\/demo1.png\" alt=\"\" width=\"1188\" height=\"437\" \/><\/a><\/p>\n<h2><a id=\"statements\"><\/a>Statements<\/h2>\n<p>RefactorScript statements are based on the C# statements. The following statements are supported:<\/p>\n<ul>\n<li>set<\/li>\n<li>foreach<\/li>\n<li>if<\/li>\n<li>else<\/li>\n<li>break<\/li>\n<li>continue<\/li>\n<li>return<\/li>\n<\/ul>\n<p>Unless otherwise noted, the syntax of the statements is the same as for the C\/C++\/C# languages. Individual statements are described below:<\/p>\n<h3><a id=\"set\"><\/a>set<\/h3>\n<p>The <strong>set<\/strong> statement creates or updates a local variable. E.g.:<\/p>\n<pre class=\"\">set tmp = 123;\r\n&gt;\/\/tmp = $tmp;<\/pre>\n<h3><a id=\"foreach\"><\/a>foreach<\/h3>\n<p>The foreach statement iterates over all of the elements of an array. Note that each element will automatically have the <strong>IsFirst<\/strong> and <strong>IsLast<\/strong> fields set depending on their position in the array, e.g. to list all arguments of a function separated by &#8220;, &#8221; use the following syntax:<\/p>\n<pre class=\"\">foreach(arg in func.Arguments)\r\n{\r\n    &gt;&gt;$arg.ShortName\r\n    if (!arg.IsLast)\r\n        &gt;&gt;, \r\n}<\/pre>\n<p>E.g. for the typical <strong>main()<\/strong> function the script above will produce &#8220;argc, argv&#8221;.<\/p>\n<h3><a id=\"if\"><\/a>if<\/h3>\n<p>The<strong> if()<\/strong> statement uses the same syntax as C\/C++\/C#. Note that each &#8220;&gt;&#8221; and &#8220;&gt;&gt;&#8221; line counts as a individual statement. I.e. the two variants shown below are equivalent (and will produce the same output as the <strong>foreach()<\/strong> example above):<\/p>\n<pre class=\"\">foreach(arg in func.Arguments)\r\n{\r\n    if (!arg.IsFirst)\r\n\t&gt;&gt;, \r\n    &gt;&gt;$arg.ShortName\r\n}<\/pre>\n<pre class=\"\">foreach(arg in func.Arguments)\r\n{\r\n    if (!arg.IsFirst)\r\n    {\r\n\t&gt;&gt;, \r\n    }\r\n    &gt;&gt;$arg.ShortName\r\n}<\/pre>\n<h2><a id=\"variables\"><\/a>Variables<\/h2>\n<p>You can set local variables using the &#8220;set&#8221; operator as shown below&#8221;, e.g.:<\/p>\n<pre class=\"\">foreach(arg in func.Arguments)\r\n{\r\n    set fieldName = arg.ShortName.UppercaseFirst().AddPrefix(\"m_\");\r\n    if (!arg.IsFirst)\r\n\t&gt;&gt;, \r\n    &gt;&gt;$fieldName\r\n}<\/pre>\n<p>For a typical <strong>main()<\/strong> function the script above will output &#8220;m_Argc, m_Argv&#8221;.<\/p>\n<p>Note that the &#8220;varName = &lt;&#8230;&gt;&#8221; expression without a &#8220;set&#8221; statement will result in an error.<\/p>\n<h2><a id=\"functions\"><\/a>Functions and Generators<\/h2>\n<p>You can define the auxiliary generators or functions called by the main generators via the <strong>generator<\/strong> and <strong>function<\/strong> keywords respectively. E.g. the code below is equivalent to the previous example:<\/p>\n<pre class=\"\">function MakeFieldName(Variable arg)\r\n{\r\n\treturn arg.ShortName.UppercaseFirst().AddPrefix(\"m_\");\r\n}\r\n\r\ngenerator OutputFieldList(Array vars)\r\n{\r\n\tforeach(arg in vars)\r\n\t{\r\n\t\tset fieldName = MakeFieldName(arg);\r\n\t\tif (!arg.IsFirst)\r\n\t\t\t&gt;&gt;, \r\n\t\t&gt;&gt;$fieldName\r\n\t}\r\n}\r\n\r\n[Main]\r\ngenerator GenerateNullChecks(Function func)\r\n{\r\n\tOutputFieldList(func.Arguments);\r\n}<\/pre>\n<p>Note that each function argument must be declared with a type. See the next section for the list of supported types.<\/p>\n<h2><a id=\"types\"><\/a>Data Types<\/h2>\n<p>RefactorScript supports 3 built-in data types (<strong>string<\/strong>, <strong>int<\/strong>, <strong>Array<\/strong>) and an alias (<strong>bool<\/strong> = <strong>int<\/strong>) that can be used to put constraints on function\/generator arguments. Additionally to them, every object describing a C\/C++ entity has an explicit type assigned to it. See the <a href=\"\/documentation\/refactorscript\/datamodel\">RefactorScript Data Model Documentation<\/a> for the list of supported types. You can also view the object types (including all parent types) via the right side of the RefactorScript window:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/10\/types.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7519\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/10\/types.png\" alt=\"\" width=\"421\" height=\"461\" \/><\/a>Note that most C\/C++ entities inherit from the <strong>Entity<\/strong> type.<\/p>\n<h3><a id=\"string\"><\/a>string<\/h3>\n<p>The string type represents a built-in string. It contains the following built-in functions:<\/p>\n<table style=\"border-collapse: collapse; width: 100%;\" border=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 50%;\">Function<\/td>\n<td style=\"width: 50%;\">Meaning<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">StripPrefix(string prefix)<\/td>\n<td style=\"width: 50%;\">If the string starts with a given prefix (e.g. &#8220;m_&#8221;), returns the string without it. Otherwise, returns the original string.<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">AddPrefix(string prefix)<\/td>\n<td style=\"width: 50%;\">Prepends a given prefix (e.g. &#8220;m_&#8221;) to the string.<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">UppercaseFirst()<\/td>\n<td style=\"width: 50%;\">Converts the first character of a string to upper case.<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">UppercaseAll()<\/td>\n<td style=\"width: 50%;\">Converts all characters of a string to upper case.<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">LowercaseFirst()<\/td>\n<td style=\"width: 50%;\">Converts the first character of a string to lower case.<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">LowercaseAll()<\/td>\n<td style=\"width: 50%;\">Converts all characters of a string to upper case.<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Trim(string chars = &#8221; \\t\\r\\n&#8221;)<\/td>\n<td style=\"width: 50%;\">Removes the specified characters from the beginning and end of the string<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">TrimStart(string chars = &#8221; \\t\\r\\n&#8221;)<\/td>\n<td style=\"width: 50%;\">Removes the specified characters from the beginning of the string<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">TrimEnd(string chars = &#8221; \\t\\r\\n&#8221;)<\/td>\n<td style=\"width: 50%;\">Removes the specified characters from the end of the string<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Contains(string str)<\/td>\n<td style=\"width: 50%;\">Returns 1 if the string contains the specified substring<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">StartsWidth(string str)<\/td>\n<td style=\"width: 50%;\">Returns 1 if the string starts with the specified substring<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">EndsWith(string str)<\/td>\n<td style=\"width: 50%;\">Returns 1 if the string ends with the specified substring<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">MatchesRegex(string regex)<\/td>\n<td style=\"width: 50%;\">Returns 1 if the string matches the given regular expression<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a id=\"array\"><\/a>Array<\/h3>\n<p>The Array type represents an array (e.g. list of class fields). You can iterate arrays via the <strong>foreach()<\/strong> statement, or use the fields below:<\/p>\n<table style=\"border-collapse: collapse; width: 100%;\" border=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 50%;\">IsEmpty<\/td>\n<td style=\"width: 50%;\">Specifies whether an array is empty<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Length<\/td>\n<td style=\"width: 50%;\">Contains the number of elements in an array<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">First<\/td>\n<td style=\"width: 50%;\">Points to the first element of the array<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Last<\/td>\n<td style=\"width: 50%;\">Points to the last element of the array<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><a id=\"args\"><\/a>Main Generator Parameters<\/h2>\n<p>The main generator of a RefactorScript can contain more than 1 parameter. VisualGDB will automatically translate them into the controls in the right side of the RefactorScript window, so that you can tweak your script behavior without having to edit it each time: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/10\/args.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7521\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/10\/args.png\" alt=\"\" width=\"1132\" height=\"622\" \/><\/a><\/p>\n<h2><a id=\"attributes\"><\/a>Attributes<\/h2>\n<p>If your script contains a single <strong>generator<\/strong> only, VisualGDB will automatically launch it when running the script. If the script contains multiple generators, use the <strong>[Main]<\/strong> attribute to mark the main generator.<\/p>\n<p>Additionally, if you provide the <strong>Description<\/strong> and <strong>SuggestFor<\/strong> attributes as shown below, VisualGDB will show the script as a smart suggestion in the code editor:<\/p>\n<pre class=\"\">[Main, Description(\"Generate NULL checks\"), SuggestFor(Function)]<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/10\/hint.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7522\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/10\/hint.png\" alt=\"\" width=\"310\" height=\"87\" \/><\/a><\/p>\n<p>You can use the following entity types in the <strong>SuggestFor<\/strong> attribute to control the contexts where the suggestion will appear:<\/p>\n<ul>\n<li>Typedef<\/li>\n<li>Enum<\/li>\n<li>Record<\/li>\n<li>Value<\/li>\n<li>Variable\n<ul>\n<li>Field<\/li>\n<li>FunctionArgument<\/li>\n<\/ul>\n<\/li>\n<li>Function<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This page provides an overview of the RefactorScript language used by VisualGDB to define custom code generation patterns. Contents Overview<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[227,239],"tags":[236,52,238],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7517"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=7517"}],"version-history":[{"count":3,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7517\/revisions"}],"predecessor-version":[{"id":7524,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7517\/revisions\/7524"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=7517"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=7517"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=7517"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}