spacemacs使用semantic跳转代码

Posted csfreebird

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spacemacs使用semantic跳转代码相关的知识,希望对你有一定的参考价值。

semantic和CEDIT的关系

semantic是CEDIT的核心,支持语义理解的代码分析。

安装semantic layer

在~/.spacemacs中配置semantic layer名称,然后重启emacs即可


跳转到打开过的buffer

安装了semantic layer之后,只要在spacemacs中打开过某个文件,就会自动建立tag,

tag目录在~/.emacs.d/.cache/semanticdb/

比如这里就有个tag文件:

~/.emacs.d/.cache/semanticdb/!home!dean!work!gitlab!gitlab.com!mystudy!mongodb!code!simple!src!helper!semantic.cache

;; Object semanticdb-project-database-file
;; SEMANTICDB Tags save file
(semanticdb-project-database-file "semanticdb-project-database-file"
  :tables
  (list
    (semanticdb-table "semanticdb-table"
      :major-mode c++-mode
      :tags 
        '( ("helper/logger.h" include nil nil [1 27])
            ("InitLog" function (:type "void") nil [29 1018]))          
      :file "logger.cc"
      :pointmax 1019
      :fsize 1018
      :lastmodtime '(22645 60456 254615 422000)
      :unmatched-syntax nil))
  :file "!home!dean!work!gitlab!gitlab.com!mystudy!mongodb!code!simple!src!helper!semantic.cache"
  :semantic-tag-version "2.0"
  :semanticdb-version "2.2")


可以看到里面有一个InitLog函数。

现在进入main.cc文件中,里面有一行调用InitLog函数的代码,将光标移动到上面,然后按下快捷键

C-c , J, 执行的是semantic-complete-jump函数。

在mini buffer中回车确认查找的是InitLog函数

然后就自动跳入源代码了。


设置变量

需要到.emacs.d/layers/+emacs/semantic/config.el中修改,比如

(setq semanticdb-find-default-throttle '(file local project unloaded system recursive))

这里加上了unloaded system recursive


不能跳入未打开buffer的问题

这是个大问题,经过了两天的探索,目前结局了第一个问题,如何跳转到有函数声明的头文件,当然如果头文件包含了内联的函数实现,就一并解决了。

答案是使用ede的帮助。

ede帮助跳入函数声明的头文件

下面是配置

  (require 'mode-local)
  (setq-mode-local c++-mode
                   semanticdb-find-default-throttle
                   '(project unloaded recursive))

  (global-ede-mode t)
  (ede-cpp-root-project "MongoDB"
                        :name "Simple Project"
                        :file "~/work/gitlab/gitlab.com/mystudy/mongodb/README.org"
                        :include-path '("/code/simple/include"
                                        "/code/simple/include/error"
                                        "/code/simple/include/helper"
                                        "/code/simple/src"
                                        "/code/simple/src/helper"
                                        )
                        :spp-table '(("isUnix" . "")
                                     ("BOOST_TEST_DYN_LINK" . "")))

用命令查看,会发现项目中include的头文件都能够被找到, 不使用ede,仅依靠semanticdb-project-roots毫无用处。

M-x semanticdb-find-adebug-scanned-includes

*scanned helper/logger.h : /home/dean/work/gitlab/gitlab.com/mystudy/mongodb/code/simple/src/main.cc
*scanned my_app.h : /home/dean/work/gitlab/gitlab.com/mystudy/mongodb/code/simple/src/main.cc
*scanned boost/filesystem.hpp : /home/dean/work/gitlab/gitlab.com/mystudy/mongodb/code/simple/src/main.cc
*scanned iostream : /home/dean/work/gitlab/gitlab.com/mystudy/mongodb/code/simple/src/main.cc
*scanned sstream : /home/dean/work/gitlab/gitlab.com/mystudy/mongodb/code/simple/src/main.cc
*scanned stdexcept : /home/dean/work/gitlab/gitlab.com/mystudy/mongodb/code/simple/src/main.cc
*scanned string : /home/dean/work/gitlab/gitlab.com/mystudy/mongodb/code/simple/src/main.cc
*scanned vector : /home/dean/work/gitlab/gitlab.com/mystudy/mongodb/code/simple/src/main.cc

在main.cc中对调用代码InitLog运行命令

M-x semantic-ia-fast-jump, 跳到logger.h文件的函数声明。

现在来解决如何跳入源代码文件的问题

跳入函数定义文件(非头文件)

感觉关键是学会使用函数

semanticdb-file-table-object

下面的文章提供了解决思路

http://www.it1352.com/483633.html

在.spacemacs文件中的user-config函数中添加这么一段

  (defvar c-files-regex ".*\\\\.\\\\(c\\\\|cpp\\\\|h\\\\|hpp\\\\|cc\\\\)"
    "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)

然后重启emacs,打开main.cc文件,运行命令加载索引

M-x ls-parse-curdir-c

然后运行命令跳转

M-x semantic-ia-fast-jump, 可以跳入函数定义文件了。

注意,此时用semanticdb-find-adebug-scanned-includes 无法观察到已经被这段程序加载的cc文件。这是一个缺憾,等以后对semantic更理解了,再来解决。


以上是关于spacemacs使用semantic跳转代码的主要内容,如果未能解决你的问题,请参考以下文章

用spacemacs打造c++ IDE

spacemacs 用semantic重构变量名

spacemacs c++代码跳转最简单的方法:rgrep

spacemacs buffer内部跳转到函数实现

Spacemacs配置yasnippe插件

通用代码编辑器Spacemacs