Semantic, cedet how to force parsing of source files
Asked Answered
B

3

6

I have been experimenting with cedet and semantic in my emacs c/c++ development setup and I am quite satisfied with it except for one small detail.

I use ede-cpp-root-project to create a project and give the root directory of my project along with the directories where include files reside like below:

(ede-cpp-root-project "My Project"
                :name "My Project"
                :file "/path/to/rootdir/AFILE"
                :include-path '( 
                "/include2"
                "/include1"
                               )

                )

This allows me to easily jump to the declarations of functions with semantic-ia-fast-jump but it does not get me to the definitions of those functions. So it seems to only be dealing with header files and totally ignore source files. Even if I go on the declaration of the function and trigger semantic-analyze-proto-impl-toggle it will tell me that no suitable implementation could be found.

If I manually open the source file where the implementation of the function is located, then and only then it is parsed by semantic and all the above mentioned functions work.

So my question is, short of manually opening all source files included underneath my project's root directory or manually including them in ede-cpp-root-project via the :spp-files argument is there any other way to force parsing of all source files under a directory?

Thanks!

Bowdlerize answered 14/8, 2013 at 11:45 Comment(0)
B
8

After ignoring this problem for a long time I thought I should spend some quality time reading on elisp and try to figure out a work-around. It is not the prettiest elisp code there is, since I use elisp only for my emacs needs but it does what I need.

(defvar c-files-regex ".*\\.\\(c\\|cpp\\|h\\|hpp\\)"
  "A regular expression to match any c/c++ related files under a directory")

(defun my-semantic-parse-dir (root regex)
  "
   This function is an attempt of mine to force semantic to
   parse all source files under a root directory. Arguments:
   -- root: The full path to the root directory
   -- regex: A regular expression against which to match all files in the directory
  "
  (let (
        ;;make sure that root has a trailing slash and is a dir
        (root (file-name-as-directory root))
        (files (directory-files root t ))
       )
    ;; remove current dir and parent dir from list
    (setq files (delete (format "%s." root) files))
    (setq files (delete (format "%s.." root) files))
    (while files
      (setq file (pop files))
      (if (not(file-accessible-directory-p file))
          ;;if it's a file that matches the regex we seek
          (progn (when (string-match-p regex file)
               (save-excursion
                 (semanticdb-file-table-object file))
           ))
          ;;else if it's a directory
          (my-semantic-parse-dir file regex)
      )
     )
  )
)

(defun my-semantic-parse-current-dir (regex)
  "
   Parses all files under the current directory matching regex
  "
  (my-semantic-parse-dir (file-name-directory(buffer-file-name)) regex)
)

(defun lk-parse-curdir-c ()
  "
   Parses all the c/c++ related files under the current directory
   and inputs their data into semantic
  "
  (interactive)
  (my-semantic-parse-current-dir c-files-regex)
)

(defun lk-parse-dir-c (dir)
  "Prompts the user for a directory and parses all c/c++ related files
   under the directory
  "
  (interactive (list (read-directory-name "Provide the directory to search in:")))
  (my-semantic-parse-dir (expand-file-name dir) c-files-regex)
)

(provide 'lk-file-search)

To use it either call the function directly like so: (my-semantic-parse-dir "path/to/dir/root/" ".*regex") or press M-x lk-parse-curdir-c from a buffer to recursively scan all c/c++ related files from that buferr's visiting filename directory.

An alternate and perhaps preferrable way to call the function is by invoking lk-parse-dir-c interactively which in turn will prompt you for a directory to parse.

If any elisp guru has a better solution or suggestions to improve the code I would love to hear them.

Bowdlerize answered 21/9, 2013 at 22:20 Comment(5)
Hey I stumbled across your blog too and this solution seems good, but emacs won't save the tags database across sessions. Am I missing something?Egor
hey, that's strange. They should be saved in a directory called .semanticdb inside your .emacs directoryBowdlerize
I had a problem where my file list was so long it was possible for emacs to stall out and seemingly make no further progress. I'm solving it by adding a call to (semanticdb-save-all-db) before we drop into the next directory. This way the cache is updated continuously. Maybe that would help. Normally semantic only saves when you exit emacs.Bloater
The regular expression is problematic. It lets everything to be parsed. A quick fix is adding $ at the end of search string. Also, the functions fail when semantic's parse fails. I am not sure if such utility exists, but a continue-with-next-file type of handling maybe appropriate when it fails to parse a particular file.Rainer
I added (semanticdb-save-all-db) , but tags not persist across sessions. And Im jumping to function prototypes, not definitions. What to do?Converse
F
1

I have implemented this for Python recently. It could be adopt for C/C++ with minor changes.

(defvar python-extention-list (list "py"))

(defun semanticdb-rescan-directory (pathname)
  (dolist (file (cddr (directory-files pathname t)))
    (if (file-directory-p file)
        (semanticdb-rescan-directory file)
      (when (member (file-name-extension file) python-extention-list)
        (message "Parsing %s file." file)
        (ignore-errors
            (semanticdb-file-table-object file))))))

(defun semantic-python-rescan-includes ()
  (interactive)
  (dolist (includes (semantic-python-get-system-include-path))
    (message "Parsing %s" includes)
    (semanticdb-rescan-directory includes)))
Fancier answered 25/7, 2014 at 16:26 Comment(0)
E
0

Try running the command "bovinate". This can be done with the key combination Meta + X and then typing "bovinate", and hitting the "Enter" key. The "Meta" key is referred to as the "Alt" key in windows.

Euchologion answered 15/8, 2013 at 22:29 Comment(1)
hey thanks for taking the time to drop a reply but I don't see how bovinate can help in my situationBowdlerize

© 2022 - 2024 — McMap. All rights reserved.