Previous: Smart Jump, Up: Analyzer

2.4.4 Debugging the Semantic Analyzer

If the Semantic Analyzer does not analyze your code properly, you can take steps to identify and solve the problem. This section was written with C/C++ in mind, but should be relevant for any typed language.

2.4.4.1 Step 1: Check the context

To check the current context, type M-x semantic-analyze-current-context.

— Command: semantic-analyze-current-context pos

Analyze the context at pos. This function is used by most of the other Semantic Analyzer commands to obtain the context of the code at a given buffer position. The return value is an EIEIO object describing the context at pos (see Top).

When called interactively, this displays a ‘*Semantic Context Analysis*’ buffer containing a summary of the context at point.

The Prefix section of the ‘*Semantic Context Analysis*’ buffer lists the tags based on the text at point. If it shows only a simple string, the Semantic was unable to identify what the data type was.

The first item in the list of the prefix is the first lookup failure in the chain, and that is the item to focus debugging effort on. For example:

     Context Type: #<semantic-analyze-context context>
     Bounds: (182 . 185)
     Prefix: Foo* bar
             int bbb (const char* y)
     Prefix Types: class Foo {}
     --------
     -> Local Vars: int argc
                    char** argv

In this example you can see that the prefix has two fully found tags. In the following example, the symbol “bbb” is incomplete, and could not be found:

     Context Type: #<semantic-analyze-context context>
     Bounds: (182 . 184)
     Prefix: Foo* bar
             "bb"
     Prefix Classes: 'function
                     'variable
     Prefix Types: class Foo {}
     --------
     -> Local Vars: int argc
                    char** argv
2.4.4.2 Step 2 : Check your include path

Once you know the missing symbol, check your include path. The header or include file containing the needed definition may not be in the list of headers Semantic is searching through. To get a basic list, you can use M-x semanticdb-find-test-translate-path. See Semanticdb search debugging commands.

If items should be loaded but aren't, or if you see some tables that have no tags in them, then you you may have an incorrectly-set search throttle (see Search Throttle). For example,

     *#<semanticdb-table main.cpp (4 tags DIRTY)>
     *#<semanticdb-table foo.hh (0 tags DIRTY)>

Here, Semantic found foo.hh, but there are 0 tags. This may be because you had set the throttle to avoid reading and parsing files that Emacs has not visited. To fix this, visit the file and let Semantic parse it.

For C++, check also that the ‘#include’ statements for your project-level files use quotes, not angle brackets; angle brackets are for system files.

2.4.4.3 Step 3: Check the local scope

If your data type is somehow abbreviated based on scope, such as from a using statement, you should make sure that the symbol you want is in the local scope. Examine the scope with M-x semantic-calculate-scope. The scope structure is displayed in ADEBUG mode, so use SPC to expand different elements and looking for your symbol.

If your symbol should be in the scope, but you cannot find it, then you may have found a language support bug in the local-variable parser, or using statement parser.

Calling M-x bovinte should force a reset on the scope in case there is merely some bad state.

      ] Name: Cache
      ] Class: #'semantic-scope-cache
      ] :table #<semanticdb-table testsubclass.cpp (13 tags DIRTY)>
      ] tag createMoose : class moose
      ] scopetypes 'nil
      ] parents #<TAG LIST: 1 entries>
      ] scope #<TAG LIST: 22 entries>
      ] fullscope #<TAG LIST: 23 entries>
      ] localvar #<TAG LIST: 6 entries>

In the above sample output, the tag slot specifies where within you source this scope is relevant. Parents should contain any in scope parents, such as the class a method belongs to. Localvar should contain your local variables. Scope should contain datatypes in scope due to a using statement or the like.

2.4.4.4 Step 4: Check the typecache

For complex typed languages like C++, Semantic creates a typecache, or an optimized search table with all the various data types in it. Elements in the typecache do not obey local scope. It only contains fully qualified names. You can examine the typecache with M-x semanticdb-typecache-dump.

If your data types are not in the typecache, there may be some parsing error or other bug. Calling M-x bovinte should force a reset on the typecache in case there is merely some bad state.

     ]#<semanticdb-typecache /home/zappo/cedet/semantic/tests/testsubclass.cpp>
        ] Name: /home/zappo/cedet/semantic/tests/testsubclass.cpp
        ] Class: #'semanticdb-typecache
        ] filestream 'nil
        ] includestream #<TAG LIST: 84 entries>
        ] stream 'nil
        ] dependants 'nil

In the above example, the output of M-x semanticdb-typecache-dump was expanded one level. The filestream slot should contain datatypes in the current file. The includestream should contain all the datatypes in all included header files.

The dependants slot will specify other files that depend on this one.

2.4.4.5 Step 5: Check the parser

Go to the location where your unfound tag should be. You can call M-x bovinate, and see a dump of the raw tag structure. To see a navigable tree, use M-x semantic-adebug-bovinate instead. You can then look to make sure your tag has been properly parsed.

If it has not, then you may have found a parser bug. To get a feel how Semantic treats your file, type M-x global-semantic-show-unmatched-syntax-mode. This causes any syntax it cannot parse to be underlined in red.

If your type is not parsable, it could be for a couple of reasons:

  1. If there is a MACRO keyword used in the definition of the type, you may need to update the semantic-lex-c-preprocessor-symbol-map to account for it.
  2. Or perhaps the parser needs to be fixed.