;;; semantic/adebug.el --- Semantic Application Debugger ;;; Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Eric M. Ludlam ;; This file is part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;; ;; Semantic datastructure debugger for semantic applications. ;; Uses data-debug for core implementation. ;; ;; Goals: ;; ;; Inspect all known details of a TAG in a buffer. ;; ;; Analyze the list of active semantic databases, and the tags therin. ;; ;; Allow interactive navigation of the analysis process, tags, etc. (require 'eieio) (require 'data-debug) (require 'semantic) (require 'semantic/tag) (require 'semantic/format) (declare-function semanticdb-get-database "semantic/db") (declare-function semanticdb-directory-loaded-p "semantic/db") (declare-function semanticdb-file-table "semantic/db") (declare-function semanticdb-needs-refresh-p "semantic/db") (declare-function semanticdb-full-filename "semantic/db") ;;; Code: ;;; SEMANTIC TAG STUFF ;; (defun data-debug-insert-tag-parts (tag prefix &optional parent) "Insert all the parts of TAG. PREFIX specifies what to insert at the start of each line. PARENT specifires any parent tag." (data-debug-insert-thing (semantic-tag-name tag) prefix "Name: " parent) (insert prefix "Class: '" (format "%S" (semantic-tag-class tag)) "\n") (when (semantic-tag-with-position-p tag) (let ((ol (semantic-tag-overlay tag)) (file (semantic-tag-file-name tag)) (start (semantic-tag-start tag)) (end (semantic-tag-end tag)) ) (insert prefix "Position: " (if (and (numberp start) (numberp end)) (format "%d -> %d in " start end) "") (if file (file-name-nondirectory file) "unknown-file") (if (semantic-overlay-p ol) " " "") "\n") (data-debug-insert-thing ol prefix "Position Data: " parent) )) (let ((attrprefix (concat (make-string (length prefix) ? ) "# "))) (insert prefix "Attributes:\n") (data-debug-insert-property-list (semantic-tag-attributes tag) attrprefix tag) (insert prefix "Properties:\n") (data-debug-insert-property-list (semantic-tag-properties tag) attrprefix tag) ) ) (defun data-debug-insert-tag-parts-from-point (point) "Call `data-debug-insert-tag-parts' based on text properties at POINT." (let ((tag (get-text-property point 'ddebug)) (parent (get-text-property point 'ddebug-parent)) (indent (get-text-property point 'ddebug-indent)) start ) (end-of-line) (setq start (point)) (forward-char 1) (data-debug-insert-tag-parts tag (concat (make-string indent ? ) "| ") parent) (goto-char start) )) (defun data-debug-insert-tag (tag prefix prebuttontext &optional parent) "Insert TAG into the current buffer at the current point. PREFIX specifies text to insert in front of TAG. PREBUTTONTEXT is text appearing btewen the prefix and TAG. Optional PARENT is the parent tag containing TAG. Add text properties needed to allow tag expansion later." (let ((start (point)) (end nil) (str (semantic-format-tag-uml-abbreviate tag parent t)) (tip (semantic-format-tag-prototype tag parent t)) ) (insert prefix prebuttontext str "\n") (setq end (point)) (put-text-property start end 'ddebug tag) (put-text-property start end 'ddebug-parent parent) (put-text-property start end 'ddebug-indent(length prefix)) (put-text-property start end 'ddebug-prefix prefix) (put-text-property start end 'help-echo tip) (put-text-property start end 'ddebug-function 'data-debug-insert-tag-parts-from-point) )) ;;; TAG LISTS ;; (defun data-debug-insert-tag-list (taglist prefix &optional parent) "Insert the tag list TAGLIST with PREFIX. Optional argument PARENT specifies the part of TAGLIST." (condition-case nil (while taglist (cond ((and (consp taglist) (semantic-tag-p (car taglist))) (data-debug-insert-tag (car taglist) prefix "" parent)) ((consp taglist) (data-debug-insert-thing (car taglist) prefix "" parent)) (t (data-debug-insert-thing taglist prefix "" parent))) (setq taglist (cdr taglist))) (error nil))) (defun data-debug-insert-taglist-from-point (point) "Insert the taglist found at the taglist button at POINT." (let ((taglist (get-text-property point 'ddebug)) (parent (get-text-property point 'ddebug-parent)) (indent (get-text-property point 'ddebug-indent)) start ) (end-of-line) (setq start (point)) (forward-char 1) (data-debug-insert-tag-list taglist (concat (make-string indent ? ) "* ") parent) (goto-char start) )) (defun data-debug-insert-tag-list-button (taglist prefix prebuttontext &optional parent) "Insert a single summary of a TAGLIST. PREFIX is the text that preceeds the button. PREBUTTONTEXT is some text between PREFIX and the taglist button. PARENT is the tag that represents the parent of all the tags." (let ((start (point)) (end nil) (str (format "#" (safe-length taglist))) (tip nil)) (insert prefix prebuttontext str) (setq end (point)) (put-text-property (- end (length str)) end 'face 'font-lock-function-name-face) (put-text-property start end 'ddebug taglist) (put-text-property start end 'ddebug-parent parent) (put-text-property start end 'ddebug-indent(length prefix)) (put-text-property start end 'ddebug-prefix prefix) (put-text-property start end 'help-echo tip) (put-text-property start end 'ddebug-function 'data-debug-insert-taglist-from-point) (insert "\n") )) ;;; SEMANTICDB FIND RESULTS ;; (defun data-debug-insert-find-results (findres prefix) "Insert the find results FINDRES with PREFIX." ;; ( (DBOBJ TAG TAG TAG) (DBOBJ TAG TAG TAG) ... ) (let ((cnt 1)) (while findres (let* ((dbhit (car findres)) (db (car dbhit)) (tags (cdr dbhit))) (data-debug-insert-thing db prefix (format "DB %d: " cnt)) (data-debug-insert-thing tags prefix (format "HITS %d: " cnt)) ) (setq findres (cdr findres) cnt (1+ cnt))))) (defun data-debug-insert-find-results-from-point (point) "Insert the find results found at the find results button at POINT." (let ((findres (get-text-property point 'ddebug)) (indent (get-text-property point 'ddebug-indent)) start ) (end-of-line) (setq start (point)) (forward-char 1) (data-debug-insert-find-results findres (concat (make-string indent ? ) "!* ") ) (goto-char start) )) (declare-function semanticdb-find-result-prin1-to-string "semantic/db-find") (defun data-debug-insert-find-results-button (findres prefix prebuttontext) "Insert a single summary of a find results FINDRES. PREFIX is the text that preceeds the button. PREBUTTONTEXT is some text between prefix and the find results button." (require 'semantic/db-find) (let ((start (point)) (end nil) (str (semanticdb-find-result-prin1-to-string findres)) (tip nil)) (insert prefix prebuttontext str) (setq end (point)) (put-text-property (- end (length str)) end 'face 'font-lock-function-name-face) (put-text-property start end 'ddebug findres) (put-text-property start end 'ddebug-indent(length prefix)) (put-text-property start end 'ddebug-prefix prefix) (put-text-property start end 'help-echo tip) (put-text-property start end 'ddebug-function 'data-debug-insert-find-results-from-point) (insert "\n") )) (defun data-debug-insert-db-and-tag-button (dbtag prefix prebuttontext) "Insert a single summary of short list DBTAG of format (DB . TAG). PREFIX is the text that preceeds the button. PREBUTTONTEXT is some text between prefix and the find results button." (let ((start (point)) (end nil) (str (concat "(#