Warning, /sdk/kde-dev-scripts/kde-emacs/kde-emacs-semantic.el is written in an unsupported language. File is not indexed.
0001 ;; kde-emacs-semantic.el
0002 ;;
0003 ;; Copyright (C) 2002 Zack Rusin <zack@kde.org>
0004 ;;
0005 ;; This library is free software; you can redistribute it and/or
0006 ;; modify it under the terms of the GNU Lesser General Public
0007 ;; License as published by the Free Software Foundation; either
0008 ;; version 2.1 of the License, or (at your option) any later version.
0009 ;;
0010 ;; This library is distributed in the hope that it will be useful,
0011 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013 ;; Lesser General Public License for more details.
0014 ;;
0015 ;; You should have received a copy of the GNU Lesser General Public
0016 ;; License along with this library; if not, write to the Free Software
0017 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0018 ;; 02110-1301 USA
0019
0020 ;;; Commentary:
0021 ;; Package provides four interactive functions:
0022 ;; - kde-function-doc-insert - creates a skeleton doxygen
0023 ;; documentation for function at point.
0024 ;; Customize it with kde-func-doc variables.
0025 ;;
0026 ;; - kde-function-expanded-at-point - returns t if function at point
0027 ;; has already been expanded.
0028 ;;
0029 ;; - kde-function-expand-at-point - expand (creates a stub) for function
0030 ;; at point (as long as function is a prototype
0031 ;; and haven't been expanded).
0032 ;;
0033 ;; - kde-create-skeletons - creates stubs for all methods in the current
0034 ;; header file.
0035 ;;
0036 ;; Package is very flexible, look at defcustom variables for things
0037 ;; you can customize.
0038
0039 ;;; Problems:
0040 ;; Most problems relate to C++ syntax which isn't handled correctly
0041 ;; by the Semantic package. For now templates aren't supported, I
0042 ;; have a temporary solution for other problems (e.g. const functions,
0043 ;; QT/KDE specific access specifiers)
0044
0045 ;;; Code:
0046 (require 'kde-emacs-vars)
0047 (require 'kde-emacs-general)
0048
0049 ;*---------------------------------------------------------------------*/
0050 ;* User configuration ... */
0051 ;*---------------------------------------------------------------------*/
0052 ;;Not yet, not yet
0053 ;(defcustom kde-summary-function 'semantic-uml-prototype-nonterminal
0054 ; "*Function to use when showing info about the token"
0055 ; :group 'kde-devel
0056 ; :type semantic-token->text-custom-list
0057 ; )
0058
0059 (defcustom kde-generate-docs-with-stubs nil
0060 "*Should function documentation be generated with the stubs."
0061 :group 'kde-devel
0062 :type 'boolean)
0063
0064 (defcustom kde-expand-arg-start "( "
0065 "*A string which specifies how the function arguments format should start.
0066 e.g. \"( \" would start function arguments list like : \"func( int arg\".
0067 and \" (\" will format the begining of the function argument list as
0068 follows : \"func (int arg\"."
0069 :group 'kde-devel
0070 :version "0.1"
0071 :type 'string)
0072
0073 (defcustom kde-expand-arg-end " )"
0074 "*Just like kde-expand-arg-start but specifies how the list should end."
0075 :group 'kde-devel
0076 :version "0.1"
0077 :type 'string)
0078
0079 (defcustom kde-expand-arg-break ", "
0080 "*Specifies how the arguments should be separated."
0081 :group 'kde-devel
0082 :version "0.1"
0083 :type 'string)
0084
0085
0086 ;*---------------------------------------------------------------------*/
0087 ;* Functions ... */
0088 ;*---------------------------------------------------------------------*/
0089 ;; FIXME : semantic doesn't handle QT access specifiers
0090 ;(setq-default global-semantic-show-unmatched-syntax-mode nil)
0091 ;(setq-default global-semantic-show-dirty-mode nil)
0092
0093 (defun kde-format-func-arg (arg)
0094 "Formats one argument (from token to string)."
0095 (let ((ret ""))
0096 (if (semantic-token-variable-extra-spec arg 'const)
0097 (setq ret "const "))
0098 (setq ret (concat ret (car (semantic-token-type arg))))
0099 (if (semantic-token-variable-extra-spec arg 'pointer)
0100 (dotimes (idx (semantic-token-variable-extra-spec arg 'pointer))
0101 (setq ret (concat ret "*"))
0102 )
0103 )
0104 (if (semantic-token-variable-extra-spec arg 'reference)
0105 (setq ret (concat ret "&"))
0106 )
0107 (setq ret (concat ret " " (semantic-token-name arg)))
0108 ret
0109 ))
0110
0111 (defun kde-format-args (token)
0112 "Formats all arguments from token to string.
0113 Token has to be the function variable list e.g.
0114 from semantic-token-function-args"
0115 (let ((res kde-expand-arg-start) (idx 1))
0116 (dolist (elt token res)
0117 (setq res (concat res (kde-format-func-arg elt)))
0118 (when (< idx (length token))
0119 (setq res (concat res kde-expand-arg-break)))
0120 (setq idx (1+ idx))
0121 )
0122 (setq res (concat res kde-expand-arg-end))
0123 ;; if it's something like "( )" replace it with "()"
0124 (when (string= res (concat kde-expand-arg-start kde-expand-arg-end))
0125 (setq res (replace-regexp-in-string "([ \t]+)" "()" res)))
0126 res
0127 ))
0128
0129 (defun kde-function-in-tokens (FUNC TOKENS)
0130 "Search for function in tokens. FUNC has to be a function
0131 token and TOKENS have to be a list of functions from buffer."
0132 (let ((ret)(elt))
0133 (while (and TOKENS (not ret))
0134 (setq elt (car TOKENS))
0135 (setq TOKENS (cdr TOKENS))
0136 (if (and (string= (semantic-token-name FUNC)
0137 (semantic-token-name elt))
0138 (equal (semantic-token-type FUNC)
0139 (semantic-token-type elt))
0140 ;; FIXME (semantic) : Functions in some classes don't have the
0141 ;; 'parent property set !!!
0142 ;;(string= (semantic-token-function-parent FUNC1)
0143 ;; (semantic-token-function-parent FUNC2))
0144 (string= (kde-format-args (semantic-token-function-args FUNC))
0145 (kde-format-args (semantic-token-function-args elt))))
0146 (setq ret t))
0147 )
0148 ret
0149 ))
0150
0151 ;; TODO support Q_SIGNALS too
0152 (defmacro kde-label-signals (pt)
0153 "Returns none-nil if the current access label == \"signals\""
0154 `(save-excursion
0155 (goto-char ,pt)
0156 (if (looking-at ":")
0157 (re-search-backward "signals" (point-at-bol) t)
0158 )
0159 ))
0160
0161 (defun kde-label-namespace (pt)
0162 "Return the namespace to which the variable/function at point PT belongs to."
0163 (save-excursion
0164 (goto-char pt)
0165 (if (looking-at "::")
0166 (let ((start) (end))
0167 (re-search-backward "\\b\\w+" (point-at-bol) t)
0168 (setq start (match-beginning 0))
0169 (setq end (match-end 0))
0170 (buffer-substring-no-properties start end)
0171 )
0172 )
0173 ))
0174
0175 (defmacro kde-label-slots (pt)
0176 "Return none-nil if at PT there's slots access specifier."
0177 `(save-excursion
0178 (goto-char ,pt)
0179 (if (looking-at ":")
0180 ;; export this regex to a kde-emacs-vars defvar
0181 (re-search-backward "\\(public\\|protected\\|private\\)[ \t]+\\(slots\\|Q_SLOTS\\)" (point-at-bol) t))
0182 ))
0183
0184 (defmacro kde-is-constructor (function)
0185 "Returns t if the FUNCTION is a constructor."
0186 `(semantic-token-function-extra-spec ,function 'constructor)
0187 )
0188
0189 (defun kde-function-const (function)
0190 "Returns t if the FUNCTION has been declared as const, e.g.
0191 if given a token representing \"int getInt() const\" this functions
0192 would return t"
0193 (save-excursion
0194 (let ((start (semantic-token-start function))
0195 (end (semantic-token-end function)))
0196 (goto-char end)
0197 (if (re-search-backward "const\b*;" start t)
0198 t
0199 nil)
0200 )
0201 ))
0202
0203 (defun kde-is-prototype (function)
0204 "Returns t if the FUNCTION is only a prototype."
0205 (cond
0206 ((semantic-token-function-extra-spec function 'prototype)
0207 t)
0208 (t
0209 (kde-function-const function))
0210 ))
0211
0212
0213
0214 (defun kde-function-at-point (pt)
0215 "Return function at pt as a token."
0216 (save-excursion
0217 (let ((token)
0218 (what (semantic-find-nonterminal-by-position pt (current-buffer)))
0219 (ctx))
0220 (goto-char pt)
0221 (if (eq (semantic-token-token what) 'function)
0222 what
0223 (semantic-find-nonterminal-by-position pt (semantic-token-type-parts what)))
0224 )
0225 ))
0226
0227 (defun kde-function-construct (token pclass)
0228 "Constructs a function string from the TOKEN, with the parent class PCLASS."
0229 (let ((fname (semantic-token-name token)))
0230 (if (semantic-token-function-destructor token)
0231 (setq fname (concat "~" fname))
0232 )
0233 (if pclass
0234 (setq fname (concat pclass "::" fname))
0235 )
0236 (if (and
0237 (not (kde-is-constructor token))
0238 (not (semantic-token-function-destructor token)))
0239 (progn
0240 (cond
0241 ((stringp (semantic-token-type token))
0242 (setq fname (concat (semantic-token-type token) "\n" fname))
0243 )
0244 (t
0245 (setq fname (concat (car (semantic-token-type token)) "\n" fname)))
0246 )
0247 (if (semantic-token-function-extra-spec token 'const)
0248 (setq fname (concat "const " fname))
0249 )
0250 )
0251 )
0252 (setq fname (concat fname (kde-format-args (semantic-token-function-args token))))
0253 (if (kde-function-const token)
0254 (setq fname (concat fname " const" ))
0255 )
0256 (setq fname (concat fname "\n{" "\n}"))
0257 fname
0258 )
0259 )
0260
0261 (defun kde-class-expand (class-token)
0262 "Returns stubs for member functions as a string.
0263 class-token has to be a token representing either a class or a struct."
0264 (let ((ret "")
0265 (name (semantic-token-name class-token))
0266 (parents (semantic-token-type-parent class-token))
0267 (parts (semantic-token-type-parts class-token))
0268 (cur-token)
0269 (cur-token-name)
0270 (asignal)
0271 (aslot)
0272 (namespace)
0273 )
0274 (dolist (elt parts ret)
0275 (setq cur-token (semantic-token-token elt))
0276 (setq cur-token-name (semantic-token-name elt))
0277 (cond
0278 ((and
0279 (eq cur-token 'type)
0280 (stringp cur-token-name))
0281 (cond
0282 ((string= cur-token-name "class")
0283 (kde-class-expand elt)
0284 )
0285 ((string= cur-token-name "enum")
0286 ;;skip enums
0287 )
0288 ((string= cur-token-name "struct")
0289 (kde-class-expand elt)
0290 )
0291 )
0292 )
0293 ((and
0294 (eq cur-token 'function)
0295 (stringp cur-token-name))
0296 ;;FUNCTION - generate a skeleton for it
0297 (if (and (kde-is-prototype elt)
0298 (not asignal))
0299 (setq ret (concat ret (kde-function-construct elt name) "\n\n"))
0300 )
0301 ;(insert (kde-function-documentation elt) "\n")
0302 )
0303 ((and
0304 (eq cur-token 'label)
0305 (stringp cur-token-name))
0306 (setq aslot nil
0307 asignal nil)
0308 ;;LABEL - unsets both signals and slots
0309 )
0310 ((and
0311 (eq cur-token 'variable)
0312 cur-token-name)
0313 ;;VARIABLE - doesn't handle static variables correctly right now
0314 )
0315 ((not (stringp cur-token-name))
0316 (cond
0317 ((kde-label-signals (car (semantic-token-extent elt)))
0318 ;;SIGNALS - next prototypes belong to signals and we don't want to
0319 ;; expand those
0320 (setq asignal t
0321 aslot nil)
0322 )
0323 ((kde-label-namespace (car (semantic-token-extent elt)))
0324 ;;NAMESPACE - semantic doesn't handle things like Qt::ButtonState correctly
0325 ;; so we do ;)
0326 (setq namespace (kde-label-namespace (car (semantic-token-extent elt))))
0327 )
0328 ((kde-label-slots (car (semantic-token-extent elt)))
0329 ;;SLOTS - for now just unset signals
0330 (setq aslot t
0331 asignal nil)
0332 )
0333 (t
0334 (insert "something else at " (number-to-string (car (semantic-token-extent elt))) "\n"))
0335 ))
0336 (t
0337 (insert "Unknown type :: " (prin1-to-string elt) " >>" (prin1-to-string cur-token) "\n"))
0338 )
0339 )
0340 ret
0341 )
0342 )
0343
0344 (defun kde-expand-tokens (tokens)
0345 "Expands smenatic tokens to strings."
0346 (let ((ret ""))
0347 (dolist (elt tokens ret)
0348 (cond
0349 ((eq (semantic-token-token elt) 'type)
0350 (setq ret (concat ret (kde-class-expand elt)))
0351 )
0352 ((eq (semantic-token-token elt) 'function)
0353 (if (kde-is-prototype elt)
0354 (setq ret (concat ret (kde-function-construct elt nil) "\n\n"))
0355 )
0356 )
0357 ((eq (semantic-token-token elt) 'variable)
0358 ;; skip
0359 ;;(kde-extract-variable elt)
0360 )
0361 ((eq (semantic-token-token elt) 'include)
0362 ;;ignore includes for now
0363 )
0364 (t (insert "Unknown type : " (prin1-to-string (semantic-token-type elt)) "\n"))
0365 )
0366 )
0367 )
0368 )
0369
0370
0371 (defun kde-tokens-in-file (FILENAME)
0372 "Returns all tokens from a file with the FILENAME."
0373 (let ((exists (file-readable-p FILENAME))
0374 (buf (current-buffer))
0375 (tokens))
0376 (if exists
0377 (progn
0378 (find-file FILENAME)
0379 (setq tokens (semantic-bovinate-toplevel t))
0380 (switch-to-buffer buf)
0381 tokens)
0382 nil)
0383 ))
0384
0385 (defun kde-function-in-file (FUNC FILENAME)
0386 "Returns non-nil if FUNC is in a file named FILENAME"
0387 (let ((tokens (kde-tokens-in-file FILENAME)))
0388 (if tokens
0389 (kde-function-in-tokens FUNC tokens)
0390 nil
0391 )
0392 ))
0393
0394 (defun kde-function-is-expanded (FUNC)
0395 "Returns t if the function FUNC has been expanded."
0396 (let ((file (kde-file-get-cpp-h)))
0397 (if (cdr file)
0398 (if (kde-function-in-file FUNC (car file))
0399 t
0400 nil
0401 )
0402 nil)
0403 ))
0404
0405 (defun kde-function-expanded-at-point (PT)
0406 "Returns non-nil if the function at point PT has already been expanded."
0407 (interactive "d")
0408 (let ((func (kde-function-at-point PT)))
0409 (kde-function-is-expanded func)
0410 )
0411 )
0412
0413 (defun kde-create-skeletons ()
0414 "Creates functions stubs in the source file, for all functions
0415 in the current header file."
0416 (interactive)
0417 (let* ((all-tokens (semantic-bovinate-toplevel t))
0418 (filename (buffer-name))
0419 (cppfile (car (kde-file-get-cpp-h)))
0420 (funcs (kde-expand-tokens all-tokens)))
0421 (find-file cppfile)
0422 (save-excursion
0423 (insert "#include \"" filename "\"\n\n")
0424 (insert funcs)
0425 )
0426 )
0427 )
0428
0429 (defun kde-function-expand-at-point (PT)
0430 "Expand function at point PT."
0431 (interactive "d")
0432 (let ((object (semantic-find-nonterminal-by-position PT (current-buffer)))
0433 (func (kde-function-at-point PT))
0434 (file)
0435 (buf)
0436 (parent))
0437 (if (and object (equal (semantic-token-type object) "class"))
0438 (setq parent (semantic-token-name object)))
0439 (if (and (not (kde-function-expanded-at-point PT))
0440 (kde-is-prototype func))
0441 (progn
0442 (setq func (kde-function-construct func parent))
0443 (setq file (car (kde-file-get-cpp-h)))
0444 (setq buf (current-buffer))
0445 (find-file file)
0446 (save-excursion
0447 (goto-char (point-max))
0448 (insert "\n" func "\n")
0449 )
0450 (switch-to-buffer buf)
0451 )
0452 (error "Function already expanded or defined!")
0453 )
0454 )
0455 )
0456
0457 (provide 'kde-emacs-semantic)