<p dir="auto">This is hopefully the last of the big TM-related refactorings from me to improve ctags parser management. I'll be nice afterwards, I promise :-).</p>
<p dir="auto">There are several problems with the current mapping done in symbols.c:</p>
<ol dir="auto">
<li>
<p dir="auto">All other language-specific mappings are done in <code>tm_parser.c</code> now<br>
and this is the only thing that is done elsewhere. Having all the<br>
mappings at one place makes things much clearer and makes <code>tm_parser.c</code><br>
the only place to play with when introducing new parser or when<br>
updating a parser to a new upstream version.</p>
</li>
<li>
<p dir="auto">The mapping is extremely confusing. First, there are several<br>
hard-coded iterator names in <a href="https://github.com/geany/geany/blob/5a369a41e3cb6fd1bc57e602fa567e8c0d153bfc/src/symbols.c#L381">TreeviewSymbols</a> which don't cover all<br>
tag types but which are just a subset of them. Then, there is<br>
<a href="https://github.com/geany/geany/blob/5a369a41e3cb6fd1bc57e602fa567e8c0d153bfc/src/symbols.c#L1022">get_tag_type_iter()</a> which is another mapping that groups certain<br>
tag types to <code>TreeViewSymbols</code> members. So when looking at mappings<br>
defined in <a href="https://github.com/geany/geany/blob/5a369a41e3cb6fd1bc57e602fa567e8c0d153bfc/src/symbols.c#L491">add_top_level_items()</a>, it isn't clear by just looking<br>
at it how tag types of certain languages get mapped to their<br>
roots without also having a look at <code>get_tag_type_iter()</code>.</p>
</li>
<li>
<p dir="auto">Since the groupings in <code>get_tag_type_iter()</code> are hard-coded,<br>
some tag types have to be grouped together whether it makes sense<br>
for the given language or not. For instance, for C we have<br>
"Typedefs / Enums" grouped together because <code>get_tag_type_iter()</code><br>
returns the same root for <code>tm_tag_typedef_t</code> and <code>tm_tag_enum_t</code><br>
and even if we wanted to change this for C, we would affect<br>
other languages too because this mapping is the same for all<br>
languages.</p>
</li>
<li>
<p dir="auto">Because of the hard-coded grouping of some tag types, we have to<br>
make a decision whether we want something to show as we want in the<br>
symbol tree or whether we map a ctags kind to tag type that is<br>
semantically close to the construct in the given language. For<br>
instance, we could separate "Typedefs / Enums" to separate roots<br>
in the symbol tree by e.g. mapping typedefs to <code>tm_tag_typedef_t</code><br>
and enums to <code>tm_tag_field_t</code> which have separate roots but then<br>
enum is represented by <code>tm_tag_field_t</code> which would confuse some<br>
more advanced Geany features like scope completion.</p>
</li>
<li>
<p dir="auto">In addition, the hard-coded grouping effectively reduces<br>
the number of roots to 11 which may not be enough for some languages.</p>
</li>
<li>
<p dir="auto">Tag icons for autocompletion popup are hard-coded in<br>
<code>get_tag_class()</code> and may differ from the icons used by the symbol<br>
tree. This isn't fixable easily with the current way of mapping.</p>
</li>
</ol>
<p dir="auto">This patch tries to solve these problems by moving root symbol<br>
tree mappings to <code>tm_parser.c</code> (so all the mappings are at one<br>
place) together with more flexible and easier to maintain<br>
way of mapping definition.</p>
<p dir="auto">For instance, consider kind mappings for the HAXE programming<br>
language which until now looked this way.</p>
<div class="snippet-clipboard-content position-relative overflow-auto" data-snippet-clipboard-copy-content="static TMParserMapEntry map_HAXE[] = {
        {'m', tm_tag_method_t},     // method
        {'c', tm_tag_class_t},      // class
        {'e', tm_tag_enum_t},       // enum
        {'v', tm_tag_variable_t},   // variable
        {'i', tm_tag_interface_t},  // interface
        {'t', tm_tag_typedef_t},    // typedef
};"><pre><code>static TMParserMapEntry map_HAXE[] = {
        {'m', tm_tag_method_t},     // method
        {'c', tm_tag_class_t},      // class
        {'e', tm_tag_enum_t},       // enum
        {'v', tm_tag_variable_t},   // variable
        {'i', tm_tag_interface_t},  // interface
        {'t', tm_tag_typedef_t},    // typedef
};
</code></pre></div>
<p dir="auto">In addition, after this patch, <code>tm_parser.c</code> contains also the<br>
following mapping for the symbol tree roots:</p>
<div class="snippet-clipboard-content position-relative overflow-auto" data-snippet-clipboard-copy-content="static TMParserMapGroup group_HAXE[] = {
        {_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
        {_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
        {_("Methods"), TM_ICON_METHOD, tm_tag_method_t},
        {_("Types"), TM_ICON_MACRO, tm_tag_typedef_t | tm_tag_enum_t},
        {_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
};"><pre><code>static TMParserMapGroup group_HAXE[] = {
        {_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
        {_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
        {_("Methods"), TM_ICON_METHOD, tm_tag_method_t},
        {_("Types"), TM_ICON_MACRO, tm_tag_typedef_t | tm_tag_enum_t},
        {_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
};
</code></pre></div>
<p dir="auto">This declaration says that there are 5 roots with the given<br>
names, icons attached to these roots, and, finally, the TM types<br>
which will appear under these roots. Notice that there may be<br>
multiple types under a single root which can be OR-d using <code>|</code><br>
because TM types are bit fields. This definition gives us enough<br>
flexibility to overcome the problems mentioned above and by having<br>
everything at one place, we can manage TM languages much more<br>
easily.</p>
<p dir="auto">There isn't anything particularly interesting about the rest of<br>
the patch - there are 2 auxiliary functions in <code>tm_parser.c/h</code>:</p>
<ul dir="auto">
<li><code>tm_parser_get_sidebar_group()</code>: returns index of a group for<br>
the provided language and TM tag type</li>
<li><code>tm_parser_get_sidebar_info()</code>: returns root name and icon<br>
for the provided language and group index</li>
</ul>
<p dir="auto">Inside <code>symbols.c</code>, <code>tv_iters</code> was converted to an array of size<br>
<code>MAX_SYMBOL_TYPES</code> of <code>GtkTreeIter</code> instead of the previous struct<br>
of hard-coded roots and the rest of the code is updated to use<br>
this array and the above 2 functions to get the mappings.</p>
<p dir="auto">TODO: Update HACKING with updated description about how to add a ctags parser (will do after a review if this patch is considered OK).</p>

<hr>

<h4>You can view, comment on, or merge this pull request online at:</h4>
<p>  <a href='https://github.com/geany/geany/pull/3137'>https://github.com/geany/geany/pull/3137</a></p>

<h4>Commit Summary</h4>
<ul>
  <li><a href="https://github.com/geany/geany/pull/3137/commits/ddbcb35d2fa2c4d0b585ce9e662098fddd288d24" class="commit-link">ddbcb35</a>  Move symbol tree root mappings to tm_parser.c</li>
  <li><a href="https://github.com/geany/geany/pull/3137/commits/6c685a3d40bf0068b2d242711a53c3b02ed65a13" class="commit-link">6c685a3</a>  Add code verifying that all tag types for a language are mapped to some group</li>
  <li><a href="https://github.com/geany/geany/pull/3137/commits/7fe3c9cb60f58e2d27e8803c44c3b47cd4d67bd0" class="commit-link">7fe3c9c</a>  Translate symbol tree roots</li>
</ul>

<h4 style="display: inline-block">File Changes </h4> <p style="display: inline-block">(<a href="https://github.com/geany/geany/pull/3137/files">4 files</a>)</p>
<ul>
  <li>
    <strong>M</strong>
    <a href="https://github.com/geany/geany/pull/3137/files#diff-fff7ef1acce73c6891e49f3a0f9a27fe31f6218afdd033ae25e39a6a6d028857">po/POTFILES.in</a>
    (1)
  </li>
  <li>
    <strong>M</strong>
    <a href="https://github.com/geany/geany/pull/3137/files#diff-57618d7b5e160a906f23885f8c59d06d88a517be568cbd428366e24b58c13fe5">src/symbols.c</a>
    (628)
  </li>
  <li>
    <strong>M</strong>
    <a href="https://github.com/geany/geany/pull/3137/files#diff-52c3ba1a920ce03ae524e393cf4d0ff582b13d9eafef29393f9841c19adf31f8">src/tagmanager/tm_parser.c</a>
    (1132)
  </li>
  <li>
    <strong>M</strong>
    <a href="https://github.com/geany/geany/pull/3137/files#diff-bf5ef327799b72933ceecfaa934a3b90ba5e983577974d2dc3a283fc4f6e8d60">src/tagmanager/tm_parser.h</a>
    (18)
  </li>
</ul>

<h4>Patch Links:</h4>
<ul>
  <li><a href='https://github.com/geany/geany/pull/3137.patch'>https://github.com/geany/geany/pull/3137.patch</a></li>
  <li><a href='https://github.com/geany/geany/pull/3137.diff'>https://github.com/geany/geany/pull/3137.diff</a></li>
</ul>

<p style="font-size:small;-webkit-text-size-adjust:none;color:#666;">—<br />Reply to this email directly, <a href="https://github.com/geany/geany/pull/3137">view it on GitHub</a>, or <a href="https://github.com/notifications/unsubscribe-auth/AAIOWJYBIPB2OKDJZWMMALTVBDS35ANCNFSM5RI7FD3Q">unsubscribe</a>.<br />You are receiving this because you are subscribed to this thread.<img src="https://github.com/notifications/beacon/AAIOWJZ367WHPK7CKWA67LLVBDS35A5CNFSM5RI7FD32YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4RQXY6BQ.gif" height="1" width="1" alt="" /><span style="color: transparent; font-size: 0; display: none; visibility: hidden; overflow: hidden; opacity: 0; width: 0; height: 0; max-width: 0; max-height: 0; mso-hide: all">Message ID: <span><geany/geany/pull/3137</span><span>@</span><span>github</span><span>.</span><span>com></span></span></p>
<script type="application/ld+json">[
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"potentialAction": {
"@type": "ViewAction",
"target": "https://github.com/geany/geany/pull/3137",
"url": "https://github.com/geany/geany/pull/3137",
"name": "View Pull Request"
},
"description": "View this Pull Request on GitHub",
"publisher": {
"@type": "Organization",
"name": "GitHub",
"url": "https://github.com"
}
}
]</script>