summaryrefslogtreecommitdiff
path: root/lisp/cedet/semantic/tag-ls.el
diff options
context:
space:
mode:
authorChong Yidong <cyd@gnu.org>2012-10-02 02:10:29 +0800
committerChong Yidong <cyd@gnu.org>2012-10-02 02:10:29 +0800
commit62a81506f802e4824b718cc30321ee3a0057cdf7 (patch)
treed681d7b767b1c3f7e4aee24ce39f6bef0d7f1f7e /lisp/cedet/semantic/tag-ls.el
parentb3317662acc0157406c20c8e14c43b7126eaa8a0 (diff)
downloademacs-62a81506f802e4824b718cc30321ee3a0057cdf7.tar.gz
Update CEDET from upstream.
Diffstat (limited to 'lisp/cedet/semantic/tag-ls.el')
-rw-r--r--lisp/cedet/semantic/tag-ls.el268
1 files changed, 237 insertions, 31 deletions
diff --git a/lisp/cedet/semantic/tag-ls.el b/lisp/cedet/semantic/tag-ls.el
index e4c248934c3..d6d2c203aa8 100644
--- a/lisp/cedet/semantic/tag-ls.el
+++ b/lisp/cedet/semantic/tag-ls.el
@@ -30,9 +30,217 @@
;; the information.
(require 'semantic)
+(require 'semantic/find)
;;; Code:
+;;; TAG SIMILARITY:
+;;
+;; Two tags that represent the same thing are "similar", but not the "same".
+;; Similar tags might have the same name, but one is a :prototype, while
+;; the other is an implementation.
+;;
+;; Each language will have different things that can be ignored
+;; between two "similar" tags, so similarity checks involve a series
+;; of mode overridable features. Some are "internal" features.
+(defvar semantic-tag-similar-ignorable-attributes '(:prototype-flag)
+ "The tag attributes that can be ignored during a similarity test.")
+
+(define-overloadable-function semantic--tag-similar-names-p (tag1 tag2 blankok)
+ "Compare the names of TAG1 and TAG2.
+If BLANKOK is false, then the names must exactly match.
+If BLANKOK is true, then if either of TAG1 or TAG2 has blank
+names, then that is ok, and this returns true, but if they both
+have values, they must still match.")
+
+(defun semantic--tag-similar-names-p-default (tag1 tag2 blankok)
+ "Compare the names of TAG1 and TAG2.
+If BLANKOK is false, then the names must exactly match.
+If BLANKOK is true, then if either of TAG1 or TAG2 has blank
+names, then that is ok, and this returns true, but if they both
+have values, they must still match."
+ (let ((n1 (semantic-tag-name tag1))
+ (n2 (semantic-tag-name tag2)))
+ (or (and blankok (or (null n1) (null n2) (string= n1 "") (string= n2 "")))
+ (string= n1 n2))))
+
+(define-overloadable-function semantic--tag-similar-types-p (tag1 tag2)
+ "Compare the types of TAG1 and TAG2.
+This functions can be overriden, for example to compare a fully
+qualified with an unqualified type."
+ (cond
+ ((and (null (semantic-tag-type tag1))
+ (null (semantic-tag-type tag2)))
+ t)
+ ((or (null (semantic-tag-type tag1))
+ (null (semantic-tag-type tag2)))
+ nil)
+ (t
+ (:override))))
+
+(defun semantic--tag-similar-types-p-default (tag1 tag2)
+ "Compare the types of TAG1 and TAG2.
+This functions can be overriden, for example to compare a fully
+qualified with an unqualified type."
+ (semantic-tag-of-type-p tag1 (semantic-tag-type tag2)))
+
+(define-overloadable-function semantic--tag-attribute-similar-p (attr value1 value2 ignorable-attributes)
+ "Test to see if attribute ATTR is similar for VALUE1 and VALUE2.
+IGNORABLE-ATTRIBUTES is described in `semantic-tag-similar-p'.
+This function is internal, but allows customization of `semantic-tag-similar-p'
+for a given mode at a more granular level.
+
+Note that :type, :name, and anything in IGNORABLE-ATTRIBUTES will
+not be passed to this function.
+
+Modes that override this function can call `semantic--tag-attribute-similar-p-default'
+to do the default equality tests if ATTR is not special for that mode.")
+
+(defun semantic--tag-attribute-similar-p-default (attr value1 value2 ignorable-attributes)
+ "For ATTR, VALUE1, VALUE2 and IGNORABLE-ATTRIBUTES, test for similarness."
+ (cond
+ ;; Tag sublists require special testing.
+ ((and (listp value1) (semantic-tag-p (car value1))
+ (listp value2) (semantic-tag-p (car value2)))
+ (let ((ans t)
+ (taglist1 value1)
+ (taglist2 value2))
+ (when (not (eq (length taglist1) (length taglist2)))
+ (setq ans nil))
+ (while (and ans taglist1 taglist2)
+ (setq ans (apply 'semantic-tag-similar-p
+ (car taglist1) (car taglist2)
+ ignorable-attributes)
+ taglist1 (cdr taglist1)
+ taglist2 (cdr taglist2)))
+ ans))
+
+ ;; The attributes are not the same?
+ ((not (equal value1 value2))
+ nil)
+
+ (t t))
+ )
+
+(define-overloadable-function semantic-tag-similar-p (tag1 tag2 &rest ignorable-attributes)
+ "Test to see if TAG1 and TAG2 are similar.
+Two tags are similar if their name, datatype, and various attributes
+are the same.
+
+Similar tags that have sub-tags such as arg lists or type members,
+are similar w/out checking the sub-list of tags.
+Optional argument IGNORABLE-ATTRIBUTES are attributes to ignore while comparing similarity.
+By default, `semantic-tag-similar-ignorable-attributes' is referenced for
+attributes, and IGNOREABLE-ATTRIBUTES will augment this list.
+
+Note that even though :name is not an attribute, it can be used to
+to indicate lax comparison of names via `semantic--tag-similar-names-p'")
+
+;; Note: optional thing is because overloadable fcns don't handle this
+;; quite right.
+(defun semantic-tag-similar-p-default (tag1 tag2 &optional ignorable-attributes)
+ "Test to see if TAG1 and TAG2 are similar.
+Two tags are similar if their name, datatype, and various attributes
+are the same.
+
+IGNORABLE-ATTRIBUTES are tag attributes that can be ignored.
+
+See `semantic-tag-similar-p' for details."
+ (let* ((ignore (append ignorable-attributes semantic-tag-similar-ignorable-attributes))
+ (A1 (and (semantic--tag-similar-names-p tag1 tag2 (memq :name ignore))
+ (semantic--tag-similar-types-p tag1 tag2)
+ (semantic-tag-of-class-p tag1 (semantic-tag-class tag2))))
+ (attr1 (semantic-tag-attributes tag1))
+ (attr2 (semantic-tag-attributes tag2))
+ (A2 t)
+ (A3 t)
+ )
+ ;; Test if there are non-ignorable attributes in A2 which are not present in A1
+ (while (and A2 attr2)
+ (let ((a (car attr2)))
+ (unless (or (eq a :type) (memq a ignore))
+ (setq A2 (semantic-tag-get-attribute tag1 a)))
+ (setq attr2 (cdr (cdr attr2)))))
+ (while (and A2 attr1 A3)
+ (let ((a (car attr1)))
+
+ (cond ((or (eq a :type) ;; already tested above.
+ (memq a ignore)) ;; Ignore them...
+ nil)
+
+ (t
+ (setq A3
+ (semantic--tag-attribute-similar-p
+ a (car (cdr attr1)) (semantic-tag-get-attribute tag2 a)
+ ignorable-attributes)))
+ ))
+ (setq attr1 (cdr (cdr attr1))))
+ (and A1 A2 A3)))
+
+;;; FULL NAMES
+;;
+;; For programmer convenience, a full name is not specified in source
+;; code. Instead some abbreviation is made, and the local environment
+;; will contain the info needed to determine the full name.
+(define-overloadable-function semantic-tag-full-package (tag &optional stream-or-buffer)
+ "Return the fully qualified package name of TAG in a package hierarchy.
+STREAM-OR-BUFFER can be anything convertible by `semantic-something-to-stream',
+but must be a toplevel semantic tag stream that contains TAG.
+A Package Hierarchy is defined in UML by the way classes and methods
+are organized on disk. Some languages use this concept such that a
+class can be accessed via it's fully qualified name, (such as Java.)
+Other languages qualify names within a Namespace (such as C++) which
+result in a different package like structure.
+
+Languages which do not override this function will just search the
+stream for a tag of class 'package, and return that."
+ (let ((stream (semantic-something-to-tag-table
+ (or stream-or-buffer tag))))
+ (:override-with-args (tag stream))))
+
+(defun semantic-tag-full-package-default (tag stream)
+ "Default method for `semantic-tag-full-package' for TAG.
+Return the name of the first tag of class `package' in STREAM."
+ (let ((pack (car-safe (semantic-find-tags-by-class 'package stream))))
+ (when (and pack (semantic-tag-p pack))
+ (semantic-tag-name pack))))
+
+(define-overloadable-function semantic-tag-full-name (tag &optional stream-or-buffer)
+ "Return the fully qualified name of TAG in the package hierarchy.
+STREAM-OR-BUFFER can be anything convertable by `semantic-something-to-stream',
+but must be a toplevel semantic tag stream that contains TAG.
+A Package Hierarchy is defined in UML by the way classes and methods
+are organized on disk. Some languages use this concept such that a
+class can be accessed via it's fully qualified name, (such as Java.)
+Other languages qualify names within a Namespace (such as C++) which
+result in a different package like structure.
+
+Languages which do not override this function with
+`tag-full-name' will combine `semantic-tag-full-package' and
+`semantic-tag-name', separated with language separator character.
+Override functions only need to handle STREAM-OR-BUFFER with a
+tag stream value, or nil.
+
+TODO - this function should probably also take a PARENT to TAG to
+resolve issues where a method in a class in a package is present."
+ (let ((stream (semantic-something-to-tag-table
+ (or stream-or-buffer tag))))
+ (:override-with-args (tag stream))))
+
+(make-obsolete-overload 'semantic-nonterminal-full-name
+ 'semantic-tag-full-name "23.2")
+
+(defun semantic-tag-full-name-default (tag stream)
+ "Default method for `semantic-tag-full-name'.
+Return the name of TAG found in the toplevel STREAM."
+ (let ((pack (semantic-tag-full-package tag stream))
+ (name (semantic-tag-name tag)))
+ (if pack
+ (concat pack
+ (car semantic-type-relation-separator-character)
+ name)
+ name)))
+
;;; UML features:
;;
;; UML can represent several types of features of a tag
@@ -93,10 +301,38 @@ See `semantic-tag-protection'."
((string= s "private")
'private)
((string= s "protected")
- 'protected)))))
+ 'protected)
+ ((string= s "package")
+ 'package)
+ ))))
(setq mods (cdr mods)))
prot))
+(defun semantic-tag-package-protected-p (tag &optional parent currentpackage)
+ "Non-nil if TAG is not available via package access control.
+For languages (such as Java) where a method is package protected,
+this method will return nil if TAG, as found in PARENT is available
+for access from a file in CURRENTPACKAGE.
+If TAG is not protected by PACKAGE, also return t. Use
+`semantic-tag-protected-p' instead.
+If PARENT is not provided, it will be derived when passed to
+`semantic-tag-protection'.
+If CURRENTPACKAGE is not provided, it will be derived from the current
+buffer."
+ (let ((tagpro (semantic-tag-protection tag parent)))
+ (if (not (eq tagpro 'package))
+ t ;; protected
+
+ ;; package protection, so check currentpackage.
+ ;; Deriving the package is better from the parent, as TAG is
+ ;; probably a field or method.
+ (if (not currentpackage)
+ (setq currentpackage (semantic-tag-full-package nil (current-buffer))))
+ (let ((tagpack (semantic-tag-full-package (or parent tag))))
+ (if (string= currentpackage tagpack)
+ nil
+ t)) )))
+
(defun semantic-tag-protected-p (tag protection &optional parent)
"Non-nil if TAG is protected.
PROTECTION is a symbol which can be returned by the method
@@ -213,36 +449,6 @@ something without an implementation."
(t nil))
))
-;;; FULL NAMES
-;;
-;; For programmer convenience, a full name is not specified in source
-;; code. Instead some abbreviation is made, and the local environment
-;; will contain the info needed to determine the full name.
-
-(define-overloadable-function semantic-tag-full-name (tag &optional stream-or-buffer)
- "Return the fully qualified name of TAG in the package hierarchy.
-STREAM-OR-BUFFER can be anything convertible by `semantic-something-to-stream',
-but must be a toplevel semantic tag stream that contains TAG.
-A Package Hierarchy is defined in UML by the way classes and methods
-are organized on disk. Some language use this concept such that a
-class can be accessed via it's fully qualified name, (such as Java.)
-Other languages qualify names within a Namespace (such as C++) which
-result in a different package like structure. Languages which do not
-override this function with `tag-full-name' will use
-`semantic-tag-name'. Override functions only need to handle
-STREAM-OR-BUFFER with a tag stream value, or nil."
- (let ((stream (semantic-something-to-tag-table
- (or stream-or-buffer tag))))
- (:override-with-args (tag stream))))
-
-(make-obsolete-overload 'semantic-nonterminal-full-name
- 'semantic-tag-full-name "23.2")
-
-(defun semantic-tag-full-name-default (tag stream)
- "Default method for `semantic-tag-full-name'.
-Return the name of TAG found in the toplevel STREAM."
- (semantic-tag-name tag))
-
(provide 'semantic/tag-ls)
;; Local variables: