cc-menus.el 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. ;;; cc-menus.el --- imenu support for CC Mode
  2. ;; Copyright (C) 1985, 1987, 1992-2015 Free Software Foundation, Inc.
  3. ;; Authors: 1998- Martin Stjernholm
  4. ;; 1992-1999 Barry A. Warsaw
  5. ;; 1987 Dave Detlefs
  6. ;; 1987 Stewart Clamen
  7. ;; 1985 Richard M. Stallman
  8. ;; Maintainer: bug-cc-mode@gnu.org
  9. ;; Created: 22-Apr-1997 (split from cc-mode.el)
  10. ;; Keywords: c languages
  11. ;; Package: cc-mode
  12. ;; This file is part of GNU Emacs.
  13. ;; GNU Emacs is free software: you can redistribute it and/or modify
  14. ;; it under the terms of the GNU General Public License as published by
  15. ;; the Free Software Foundation, either version 3 of the License, or
  16. ;; (at your option) any later version.
  17. ;; GNU Emacs is distributed in the hope that it will be useful,
  18. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. ;; GNU General Public License for more details.
  21. ;; You should have received a copy of the GNU General Public License
  22. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  23. ;;; Commentary:
  24. ;;; Code:
  25. (eval-when-compile
  26. (let ((load-path
  27. (if (and (boundp 'byte-compile-dest-file)
  28. (stringp byte-compile-dest-file))
  29. (cons (file-name-directory byte-compile-dest-file) load-path)
  30. load-path)))
  31. (load "cc-bytecomp" nil t)))
  32. (cc-require 'cc-defs)
  33. ;; The things referenced in imenu, which we don't require.
  34. (cc-bytecomp-defvar imenu-case-fold-search)
  35. (cc-bytecomp-defvar imenu-generic-expression)
  36. (cc-bytecomp-defvar imenu-create-index-function)
  37. ;; imenu integration
  38. (defvar cc-imenu-c-prototype-macro-regexp nil
  39. "RE matching macro names used to conditionally specify function prototypes.
  40. For example:
  41. #ifdef __STDC__
  42. #define _P(x) x
  43. #else
  44. #define _P(x) /*nothing*/
  45. #endif
  46. int main _P( (int argc, char *argv[]) )
  47. A sample value might look like: `\\(_P\\|_PROTO\\)'.")
  48. ;; *Warning for cc-mode developers*
  49. ;;
  50. ;; `cc-imenu-objc-generic-expression' elements depend on
  51. ;; `cc-imenu-c++-generic-expression'. So if you change this
  52. ;; expression, you need to change following variables,
  53. ;; `cc-imenu-objc-generic-expression-*-index',
  54. ;; too. `cc-imenu-objc-function' uses these *-index variables, in
  55. ;; order to know where the each regexp *group \\(foobar\\)* elements
  56. ;; are started.
  57. ;;
  58. ;; *-index variables are initialized during `cc-imenu-objc-generic-expression'
  59. ;; being initialized.
  60. ;;
  61. (defvar cc-imenu-c++-generic-expression
  62. `(
  63. ;; Try to match ::operator definitions first. Otherwise `X::operator new ()'
  64. ;; will be incorrectly recognized as function `new ()' because the regexps
  65. ;; work by backtracking from the end of the definition.
  66. (nil
  67. ,(concat
  68. "^\\<.*"
  69. "[^" c-alnum "_:<>~]" ; match any non-identifier char
  70. ; (note: this can be `\n')
  71. "\\("
  72. "\\([" c-alnum "_:<>~]*::\\)?" ; match an operator
  73. "operator\\>[ \t]*"
  74. "\\(()\\|[^(]*\\)" ; special case for `()' operator
  75. "\\)"
  76. "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list,
  77. ; require something other than
  78. ; a `;' after the (...) to
  79. ; avoid prototypes. Can't
  80. ; catch cases with () inside
  81. ; the parentheses surrounding
  82. ; the parameters. e.g.:
  83. ; `int foo(int a=bar()) {...}'
  84. ) 1)
  85. ;; Special case to match a line like `main() {}'
  86. ;; e.g. no return type, not even on the previous line.
  87. (nil
  88. ,(concat
  89. "^"
  90. "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name
  91. "[ \t]*(" ; see above, BUT
  92. "[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start
  93. "[ \t]*[^ \t;(]" ; with an asterisk or parentheses
  94. ) 1)
  95. ;; General function name regexp
  96. (nil
  97. ,(concat
  98. "^\\<" ; line MUST start with word char
  99. ;; \n added to prevent overflow in regexp matcher.
  100. ;; http://lists.gnu.org/archive/html/emacs-pretest-bug/2007-02/msg00021.html
  101. "[^()\n]*" ; no parentheses before
  102. "[^" c-alnum "_:<>~]" ; match any non-identifier char
  103. "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name
  104. "\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list
  105. "\\([ \t\n]\\|\\\\\n\\)*" ; must not start
  106. "\\([^ \t\n(*]" ; with an asterisk or parentheses
  107. "[^()]*\\(([^()]*)[^()]*\\)*" ; Maybe function pointer arguments
  108. "\\)?)"
  109. "\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]"
  110. ) 1)
  111. ;; Special case for definitions using phony prototype macros like:
  112. ;; `int main _PROTO( (int argc,char *argv[]) )'.
  113. ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set.
  114. ;; Only supported in c-code, so no `:<>~' chars in function name!
  115. ,@(if cc-imenu-c-prototype-macro-regexp
  116. `((nil
  117. ,(concat
  118. "^\\<.*" ; line MUST start with word char
  119. "[^" c-alnum "_]" ; match any non-identifier char
  120. "\\([" c-alpha "_][" c-alnum "_]*\\)" ; match function name
  121. "[ \t]*" ; whitespace before macro name
  122. cc-imenu-c-prototype-macro-regexp
  123. "[ \t]*(" ; ws followed by first paren.
  124. "[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above
  125. ) 1)))
  126. ;; Class definitions
  127. ("Class"
  128. ,(concat
  129. "^" ; beginning of line is required
  130. "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>'
  131. "\\(class\\|struct\\)[ \t]+"
  132. "\\(" ; the string we want to get
  133. "[" c-alnum "_]+" ; class name
  134. "\\(<[^>]+>\\)?" ; possibly explicitly specialized
  135. "\\)"
  136. "\\([ \t\n]\\|\\\\\n\\)*[:{]"
  137. ) 3))
  138. "Imenu generic expression for C++ mode. See `imenu-generic-expression'.")
  139. (defvar cc-imenu-c-generic-expression
  140. cc-imenu-c++-generic-expression
  141. "Imenu generic expression for C mode. See `imenu-generic-expression'.")
  142. ;; Auxiliary regexps for Java try to match their trailing whitespace where
  143. ;; appropriate, but _not_ starting whitespace.
  144. (defconst cc-imenu-java-ellipsis-regexp
  145. (concat
  146. "\\.\\{3\\}"
  147. "[ \t\n\r]*"))
  148. (defun cc-imenu-java-build-type-args-regex (depth)
  149. "Builds regexp for type arguments list with DEPTH allowed
  150. nested angle brackets constructs."
  151. (if (> depth 0)
  152. (concat "<"
  153. "[][.," c-alnum "_? \t\n\r]+"
  154. (if (> depth 1)
  155. "\\(")
  156. (cc-imenu-java-build-type-args-regex (1- depth))
  157. (if (> depth 1)
  158. (concat "[][.," c-alnum "_? \t\n\r]*"
  159. "\\)*"))
  160. ">")))
  161. (defconst cc-imenu-java-type-spec-regexp
  162. (concat
  163. ;; zero or more identifiers followed by a dot
  164. "\\("
  165. "[" c-alpha "_][" c-alnum "_]*\\."
  166. "\\)*"
  167. ;; a single mandatory identifier without a dot
  168. "[" c-alpha "_][" c-alnum "_]*"
  169. ;; then choice:
  170. "\\("
  171. ;; (option 1) type arguments list which _may_ be followed with brackets
  172. ;; and/or spaces, then optional variable arity
  173. "[ \t\n\r]*"
  174. (cc-imenu-java-build-type-args-regex 3)
  175. "[][ \t\n\r]*"
  176. "\\(" cc-imenu-java-ellipsis-regexp "\\)?"
  177. "\\|"
  178. ;; (option 2) just brackets and/or spaces (there should be at least one),
  179. ;; then optional variable arity
  180. "[][ \t\n\r]+"
  181. "\\(" cc-imenu-java-ellipsis-regexp "\\)?"
  182. "\\|"
  183. ;; (option 3) just variable arity
  184. cc-imenu-java-ellipsis-regexp
  185. "\\)"))
  186. (defconst cc-imenu-java-comment-regexp
  187. (concat
  188. "/"
  189. "\\("
  190. ;; a traditional comment
  191. "\\*"
  192. "\\("
  193. "[^*]"
  194. "\\|"
  195. "\\*+[^/*]"
  196. "\\)*"
  197. "\\*+/"
  198. "\\|"
  199. ;; an end-of-line comment
  200. "/[^\n\r]*[\n\r]"
  201. "\\)"
  202. "[ \t\n\r]*"
  203. ))
  204. ;; Comments are allowed before the argument, after any of the
  205. ;; modifiers and after the identifier.
  206. (defconst cc-imenu-java-method-arg-regexp
  207. (concat
  208. "\\(" cc-imenu-java-comment-regexp "\\)*"
  209. ;; optional modifiers
  210. "\\("
  211. ;; a modifier is either an annotation or "final"
  212. "\\("
  213. "@[" c-alpha "_]"
  214. "[" c-alnum "._]*"
  215. ;; TODO support element-value pairs!
  216. "\\|"
  217. "final"
  218. "\\)"
  219. ;; a modifier ends with comments and/or ws
  220. "\\("
  221. "\\(" cc-imenu-java-comment-regexp "\\)+"
  222. "\\|"
  223. "[ \t\n\r]+"
  224. "\\(" cc-imenu-java-comment-regexp "\\)*"
  225. "\\)"
  226. "\\)*"
  227. ;; type spec
  228. cc-imenu-java-type-spec-regexp
  229. ;; identifier
  230. "[" c-alpha "_]"
  231. "[" c-alnum "_]*"
  232. ;; optional comments and/or ws
  233. "[ \t\n\r]*"
  234. "\\(" cc-imenu-java-comment-regexp "\\)*"
  235. ))
  236. (defconst cc-imenu-java-generic-expression
  237. `((nil
  238. ,(concat
  239. cc-imenu-java-type-spec-regexp
  240. "\\(" ; method name which gets captured
  241. ; into index
  242. "[" c-alpha "_]"
  243. "[" c-alnum "_]*"
  244. "\\)"
  245. "[ \t\n\r]*"
  246. ;; An argument list that contains zero or more arguments.
  247. (concat
  248. "("
  249. "[ \t\n\r]*"
  250. "\\("
  251. "\\(" cc-imenu-java-method-arg-regexp ",[ \t\n\r]*\\)*"
  252. cc-imenu-java-method-arg-regexp
  253. "\\)?"
  254. ")"
  255. "[.,_" c-alnum " \t\n\r]*" ; throws etc.
  256. "{"
  257. )) 7))
  258. "Imenu generic expression for Java mode. See `imenu-generic-expression'.")
  259. ;; Internal variables
  260. (defvar cc-imenu-objc-generic-expression-noreturn-index nil)
  261. (defvar cc-imenu-objc-generic-expression-general-func-index nil)
  262. (defvar cc-imenu-objc-generic-expression-proto-index nil)
  263. (defvar cc-imenu-objc-generic-expression-objc-base-index nil)
  264. (defvar cc-imenu-objc-generic-expression
  265. (concat
  266. ;;
  267. ;; For C
  268. ;;
  269. ;; > Special case to match a line like `main() {}'
  270. ;; > e.g. no return type, not even on the previous line.
  271. ;; Pick a token by (match-string 1)
  272. (car (cdr (nth 1 cc-imenu-c++-generic-expression))) ; -> index += 2
  273. (prog2 (setq cc-imenu-objc-generic-expression-noreturn-index 1) "")
  274. "\\|"
  275. ;; > General function name regexp
  276. ;; Pick a token by (match-string 3)
  277. (car (cdr (nth 2 cc-imenu-c++-generic-expression))) ; -> index += 6
  278. (prog2 (setq cc-imenu-objc-generic-expression-general-func-index 3) "")
  279. ;; > Special case for definitions using phony prototype macros like:
  280. ;; > `int main _PROTO( (int argc,char *argv[]) )'.
  281. ;; Pick a token by (match-string 8)
  282. (if cc-imenu-c-prototype-macro-regexp
  283. (concat
  284. "\\|"
  285. (car (cdr (nth 3 cc-imenu-c++-generic-expression))) ; -> index += 1
  286. (prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 10) "")
  287. )
  288. (prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 9) "")
  289. "") ; -> index += 0
  290. (prog2 (setq cc-imenu-objc-generic-expression-proto-index 9) "")
  291. ;;
  292. ;; For Objective-C
  293. ;; Pick a token by (match-string 8 or 9)
  294. ;;
  295. "\\|\\("
  296. "^[-+][:" c-alnum "()*_<>\n\t ]*[;{]" ; Methods
  297. "\\|"
  298. "^@interface[\t ]+[" c-alnum "_]+[\t ]*:"
  299. "\\|"
  300. "^@interface[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)"
  301. "\\|"
  302. ;; For NSObject, NSProxy and Object... They don't have super class.
  303. "^@interface[\t ]+[" c-alnum "_]+[\t ]*.*$"
  304. "\\|"
  305. "^@implementation[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)"
  306. "\\|"
  307. "^@implementation[\t ]+[" c-alnum "_]+"
  308. "\\|"
  309. "^@protocol[\t ]+[" c-alnum "_]+" "\\)")
  310. "Imenu generic expression for ObjC mode. See `imenu-generic-expression'.")
  311. ;; Imenu support for objective-c uses functions.
  312. (defsubst cc-imenu-objc-method-to-selector (method)
  313. "Return the objc selector style string of METHOD.
  314. Example:
  315. - perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */
  316. =>
  317. -perform:withObject:withObject:withObject: /* selector */"
  318. (let ((return "") ; String to be returned
  319. (p 0) ; Current scanning position in METHOD
  320. (pmax (length method)) ;
  321. char ; Current scanning target
  322. (betweenparen 0) ; CHAR is in parentheses.
  323. argreq ; An argument is required.
  324. inargvar) ; position of CHAR is in an argument variable.
  325. (while (< p pmax)
  326. (setq char (aref method p)
  327. p (1+ p))
  328. (cond
  329. ;; Is CHAR part of a objc token?
  330. ((and (not inargvar) ; Ignore if CHAR is part of an argument variable.
  331. (eq 0 betweenparen) ; Ignore if CHAR is in parentheses.
  332. (or (and (<= ?a char) (<= char ?z))
  333. (and (<= ?A char) (<= char ?Z))
  334. (and (<= ?0 char) (<= char ?9))
  335. (= ?_ char)))
  336. (if argreq
  337. (setq inargvar t
  338. argreq nil)
  339. (setq return (concat return (char-to-string char)))))
  340. ;; Or a white space?
  341. ((and inargvar (or (eq ?\ char) (eq ?\n char))
  342. (setq inargvar nil)))
  343. ;; Or a method separator?
  344. ;; If a method separator, the next token will be an argument variable.
  345. ((eq ?: char)
  346. (setq argreq t
  347. return (concat return (char-to-string char))))
  348. ;; Or an open parentheses?
  349. ((eq ?\( char)
  350. (setq betweenparen (1+ betweenparen)))
  351. ;; Or a close parentheses?
  352. ((eq ?\) char)
  353. (setq betweenparen (1- betweenparen)))))
  354. return))
  355. (defun cc-imenu-objc-remove-white-space (str)
  356. "Remove all spaces and tabs from STR."
  357. (let ((return "")
  358. (p 0)
  359. (max (length str))
  360. char)
  361. (while (< p max)
  362. (setq char (aref str p))
  363. (setq p (1+ p))
  364. (if (or (= char ?\ ) (= char ?\t))
  365. ()
  366. (setq return (concat return (char-to-string char)))))
  367. return))
  368. (defun cc-imenu-objc-function ()
  369. "Imenu support for Objective C mode."
  370. (let (methodlist
  371. clist
  372. ;;
  373. ;; OBJC, Cnoreturn, Cgeneralfunc, Cproto are constants.
  374. ;;
  375. ;; *Warning for developers*
  376. ;; These constants depend on `cc-imenu-c++-generic-expression'.
  377. ;;
  378. (OBJC cc-imenu-objc-generic-expression-objc-base-index)
  379. ;; Special case to match a line like `main() {}'
  380. (Cnoreturn cc-imenu-objc-generic-expression-noreturn-index)
  381. ;; General function name regexp
  382. (Cgeneralfunc cc-imenu-objc-generic-expression-general-func-index)
  383. ;; Special case for definitions using phony prototype macros like:
  384. (Cproto cc-imenu-objc-generic-expression-proto-index)
  385. langnum
  386. ;;
  387. (classcount 0)
  388. toplist
  389. str
  390. str2
  391. (intflen (length "@interface"))
  392. (implen (length "@implementation"))
  393. (prtlen (length "@protocol"))
  394. (func
  395. ;;
  396. ;; Does this emacs have buffer-substring-no-properties?
  397. ;;
  398. (if (fboundp 'buffer-substring-no-properties)
  399. 'buffer-substring-no-properties
  400. 'buffer-substring)))
  401. (goto-char (point-max))
  402. ;;
  403. (while (re-search-backward cc-imenu-objc-generic-expression nil t)
  404. (setq langnum (if (match-beginning OBJC)
  405. OBJC
  406. (cond
  407. ((match-beginning Cproto) Cproto)
  408. ((match-beginning Cgeneralfunc) Cgeneralfunc)
  409. ((match-beginning Cnoreturn) Cnoreturn))))
  410. (setq str (funcall func (match-beginning langnum) (match-end langnum)))
  411. ;;
  412. (cond
  413. ;;
  414. ;; C
  415. ;;
  416. ((not (eq langnum OBJC))
  417. (setq clist (cons (cons str (match-beginning langnum)) clist)))
  418. ;;
  419. ;; ObjC
  420. ;;
  421. ;; An instance Method
  422. ((eq (aref str 0) ?-)
  423. (setq str (concat "-" (cc-imenu-objc-method-to-selector str)))
  424. (setq methodlist (cons (cons str
  425. (match-beginning langnum))
  426. methodlist)))
  427. ;; A factory Method
  428. ((eq (aref str 0) ?+)
  429. (setq str (concat "+" (cc-imenu-objc-method-to-selector str)))
  430. (setq methodlist (cons (cons str
  431. (match-beginning langnum))
  432. methodlist)))
  433. ;; Interface or implementation or protocol
  434. ((eq (aref str 0) ?@)
  435. (setq classcount (1+ classcount))
  436. (cond
  437. ((and (> (length str) implen)
  438. (string= (substring str 0 implen) "@implementation"))
  439. (setq str (substring str implen)
  440. str2 "@implementation"))
  441. ((string= (substring str 0 intflen) "@interface")
  442. (setq str (substring str intflen)
  443. str2 "@interface"))
  444. ((string= (substring str 0 prtlen) "@protocol")
  445. (setq str (substring str prtlen)
  446. str2 "@protocol")))
  447. (setq str (cc-imenu-objc-remove-white-space str))
  448. (setq methodlist (cons (cons str2
  449. (match-beginning langnum))
  450. methodlist))
  451. (setq toplist (cons (cons str methodlist) toplist)
  452. methodlist nil))))
  453. ;; In this buffer, there is only one or zero @{interface|implementation|protocol}.
  454. (if (< classcount 2)
  455. (let ((classname (car (car toplist)))
  456. (p (cdr (car (cdr (car toplist)))))
  457. last)
  458. (setq toplist (cons (cons classname p) (cdr (cdr (car toplist)))))
  459. ;; Add C lang token
  460. (if clist
  461. (progn
  462. (setq last toplist)
  463. (while (cdr last)
  464. (setq last (cdr last)))
  465. (setcdr last clist))))
  466. ;; Add C lang tokens as a sub menu
  467. (if clist
  468. (setq toplist (cons (cons "C" clist) toplist))))
  469. ;;
  470. toplist
  471. ))
  472. ;(defvar cc-imenu-pike-generic-expression
  473. ; ())
  474. ; FIXME: Please contribute one!
  475. (defun cc-imenu-init (mode-generic-expression
  476. &optional mode-create-index-function)
  477. (setq imenu-generic-expression mode-generic-expression
  478. imenu-case-fold-search nil)
  479. (when mode-create-index-function
  480. (setq imenu-create-index-function mode-create-index-function)))
  481. (cc-provide 'cc-menus)
  482. ;; Local Variables:
  483. ;; indent-tabs-mode: t
  484. ;; tab-width: 8
  485. ;; End:
  486. ;;; cc-menus.el ends here