]> code.delx.au - gnu-emacs/blobdiff - lisp/cedet/semantic/scope.el
Update copyright year to 2015
[gnu-emacs] / lisp / cedet / semantic / scope.el
index a8654e90c07c485e70ed2b00fef2e367f3558553..2c0dea20107be9cf86cd38f6ad2dd311eed0f18c 100644 (file)
@@ -1,6 +1,6 @@
 ;;; semantic/scope.el --- Analyzer Scope Calculations
 
-;; Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2015 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <eric@siege-engine.com>
 
@@ -24,7 +24,7 @@
 ;; Calculate information about the current scope.
 ;;
 ;; Manages the current scope as a structure that can be cached on a
-;; per-file basis and recycled between different occurances of
+;; per-file basis and recycled between different occurrences of
 ;; analysis on different parts of a file.
 ;;
 ;; Pattern for Scope Calculation
@@ -56,6 +56,7 @@
 (declare-function semantic-analyze-princ-sequence "semantic/analyze")
 (declare-function semanticdb-typecache-merge-streams "semantic/db-typecache")
 (declare-function semanticdb-typecache-add-dependant "semantic/db-typecache")
+(declare-function semantic-tag-similar-p "semantic/tag-ls")
 
 ;;; Code:
 
@@ -67,7 +68,7 @@
               :documentation
               "The list of types currently in scope.
 For C++, this would contain anonymous namespaces known, and
-anything labled by a `using' statement.")
+anything labeled by a `using' statement.")
    (parents :initform nil
            :documentation
            "List of parents in scope w/in the body of this function.
@@ -158,7 +159,7 @@ If nil, then the typescope is reset."
 ;; tag can be passed in and a scope derived from it.
 
 (defun semantic-scope-tag-clone-with-scope (tag scopetags)
-  "Close TAG, and return it.  Add SCOPETAGS as a tag-local scope.
+  "Clone TAG, and return it.  Add SCOPETAGS as a tag-local scope.
 Stores the SCOPETAGS as a set of tag properties on the cloned tag."
   (let ((clone (semantic-tag-clone tag))
        )
@@ -186,7 +187,7 @@ Use `semantic-ctxt-scoped-types' to find types."
   (save-excursion
     (goto-char position)
     (let ((code-scoped-types nil))
-      ;; Lets ask if any types are currently scoped.  Scoped
+      ;; Let's ask if any types are currently scoped.  Scoped
       ;; classes and types provide their public methods and types
       ;; in source code, but are unrelated hierarchically.
       (let ((sp (semantic-ctxt-scoped-types)))
@@ -194,12 +195,18 @@ Use `semantic-ctxt-scoped-types' to find types."
          ;; Get this thing as a tag
          (let ((tmp (cond
                      ((stringp (car sp))
-                      (semanticdb-typecache-find (car sp)))
-                      ;(semantic-analyze-find-tag (car sp) 'type))
+                      (or (semanticdb-typecache-find (car sp))
+                          ;; If we did not find it in the typecache,
+                          ;; look in the tags we found so far
+                          (car (semantic-deep-find-tags-by-name
+                                (car sp)
+                                code-scoped-types))))
                      ((semantic-tag-p (car sp))
-                      (if (semantic-analyze-tag-prototype-p (car sp))
-                          (semanticdb-typecache-find (semantic-tag-name (car sp)))
-                          ;;(semantic-analyze-find-tag (semantic-tag-name (car sp)) 'type)
+                      (if (semantic-tag-prototype-p (car sp))
+                          (or (semanticdb-typecache-find (semantic-tag-name (car sp)))
+                              (car (semantic-deep-find-tags-by-name
+                                    (semantic-tag-name (car sp))
+                                    code-scoped-types)))
                         (car sp)))
                      (t nil))))
            (when tmp
@@ -239,14 +246,17 @@ are from nesting data types."
           )
       ;; In case of arg lists or some-such, throw out non-types.
       (while (and stack (not (semantic-tag-of-class-p pparent 'type)))
-       (setq stack (cdr stack)
-                   pparent (car (cdr stack))))
+       (setq stack (cdr stack) pparent (car (cdr stack))))
+
+      ;; Remove duplicates
+      (while (member pparent scopetypes)
+       (setq stack (cdr stack) pparent (car (cdr stack))))
 
       ;; Step 1:
       ;;    Analyze the stack of tags we are nested in as parents.
       ;;
 
-      ;; If we have a pparent tag, lets go there
+      ;; If we have a pparent tag, let's go there
       ;; an analyze that stack of tags.
       (when (and pparent (semantic-tag-with-position-p pparent))
        (semantic-go-to-tag pparent)
@@ -268,9 +278,11 @@ are from nesting data types."
            (setq stack (reverse stack))
            ;; Add things to STACK until we cease finding tags of class type.
            (while (and stack (eq (semantic-tag-class (car stack)) 'type))
-             ;; Otherwise, just add this to the returnlist.
-             (setq returnlist (cons (car stack) returnlist))
-             (setq stack (cdr stack)))
+             ;; Otherwise, just add this to the returnlist, but make
+             ;; sure we didn't already have that tag in scopetypes
+             (unless (member (car stack) scopetypes)
+               (setq returnlist (cons (car stack) returnlist)))
+            (setq stack (cdr stack)))
 
            (setq returnlist (nreverse returnlist))
            ))
@@ -300,7 +312,7 @@ are from nesting data types."
                   (miniscope (semantic-scope-cache "mini"))
                   ptag)
 
-             ;; Find the next entry in the refereneced type for
+             ;; Find the next entry in the referenced type for
              ;; our function, and append to return list till our
              ;; returnlist is empty.
              (while snlist
@@ -381,14 +393,14 @@ be found."
 ;;------------------------------------------------------------
 
 (define-overloadable-function semantic-analyze-scoped-tags (typelist parentlist)
-  "Return accessable tags when TYPELIST and PARENTLIST is in scope.
+  "Return accessible tags when TYPELIST and PARENTLIST is in scope.
 Tags returned are not in the global name space, but are instead
 scoped inside a class or namespace.  Such items can be referenced
 without use of \"object.function()\" style syntax due to an
 implicit \"object\".")
 
 (defun semantic-analyze-scoped-tags-default (typelist halfscope)
-  "Return accessable tags when TYPELIST and HALFSCOPE is in scope.
+  "Return accessible tags when TYPELIST and HALFSCOPE is in scope.
 HALFSCOPE is the current scope partially initialized.
 Tags returned are not in the global name space, but are instead
 scoped inside a class or namespace.  Such items can be referenced
@@ -409,7 +421,7 @@ implicit \"object\"."
          ))
       (setq typelist (cdr typelist)))
 
-    ;; Loop over the types (which should be sorted by postion
+    ;; Loop over the types (which should be sorted by position)
     ;; adding to the scopelist as we go, and using the scopelist
     ;; for additional searching!
     (while typelist2
@@ -421,9 +433,9 @@ implicit \"object\"."
                          currentscope))
       (setq typelist2 (cdr typelist2)))
 
-    ;; Collect all the types (class, etc) that are in our heratage.
+    ;; Collect all the types (class, etc) that are in our heritage.
     ;; These are types that we can extract members from, not those
-    ;; delclared in using statements, or the like.
+    ;; declared in using statements, or the like.
     ;; Get the PARENTS including nesting scope for this location.
     (while parentlist
       (oset miniscope scope currentscope)
@@ -500,10 +512,33 @@ tag is not something you can complete from within TYPE."
        (leftover nil)
        )
     (dolist (S allslots)
-      (when (or (not (semantic-tag-of-class-p S 'function))
-               (not (semantic-tag-function-parent S)))
-       (setq leftover (cons S leftover)))
-      )
+      ;; We have to specially deal with 'using' tags here, since those
+      ;; pull in namespaces or classes into the current scope.
+      ;; (Should this go into c.el? If so, into which override?)
+      (if (semantic-tag-of-class-p S 'using)
+         (let* ((fullname (semantic-analyze-unsplit-name
+                           (list (semantic-tag-name type)
+                                 (semantic-tag-name S))))
+                ;; Search the typecache, first for the unqualified name
+                (usingtype (or
+                             (semanticdb-typecache-find (semantic-tag-name S))
+                             ;; If that didn't return anything, use
+                             ;; fully qualified name
+                             (semanticdb-typecache-find fullname)))
+                (filename (when usingtype (semantic-tag-file-name usingtype))))
+           (when usingtype
+             ;; Use recursion to examine that namespace or class
+             (let ((tags (semantic-completable-tags-from-type usingtype)))
+               (if filename
+                   ;; If we have a filename, copy the tags with it
+                   (dolist (cur tags)
+                     (setq leftover (cons (semantic-tag-copy cur nil filename)
+                                          leftover)))
+                 ;; Otherwise just run with it
+                 (setq leftover (append tags leftover))))))
+       (when (or (not (semantic-tag-of-class-p S 'function))
+                 (not (semantic-tag-function-parent S)))
+         (setq leftover (cons S leftover)))))
     (nreverse leftover)))
 
 (defun semantic-analyze-scoped-type-parts (type &optional scope noinherit protection)
@@ -556,8 +591,8 @@ PROTECTION specifies the type of access requested, such as 'public or 'private."
 Argument SCOPE specify additional tags that are in scope
 whose tags can be searched when needed, OR it may be a scope object.
 ACCESS is the level of access we filter on child supplied tags.
-For langauges with protection on specific methods or slots,
-it should strip out those not accessable by methods of TYPE.
+For languages with protection on specific methods or slots,
+it should strip out those not accessible by methods of TYPE.
 An ACCESS of 'public means not in a method of a subclass of type.
 A value of 'private means we can access private parts of the originating
 type."
@@ -602,28 +637,29 @@ whose tags can be searched when needed, OR it may be a scope object."
       ;;         for recycling later?  Should this become a helpful
       ;;         extra routine?
       (when (and parents (semantic-tag-with-position-p type))
-       ;; If TYPE has a position, go there and get the scope.
-       (semantic-go-to-tag type)
-
-       ;; We need to make a mini scope, and only include the misc bits
-       ;; that will help in finding the parent.  We don't really need
-       ;; to do any of the stuff related to variables and what-not.
-       (setq tmpscope (semantic-scope-cache "mini"))
-       (let* (;; Step 1:
-              (scopetypes (semantic-analyze-scoped-types (point)))
-              (parents (semantic-analyze-scope-nested-tags (point) scopetypes))
-              ;;(parentinherited (semantic-analyze-scope-lineage-tags parents scopetypes))
-              (lscope nil)
-              )
-         (oset tmpscope scopetypes scopetypes)
-         (oset tmpscope parents parents)
-         ;;(oset tmpscope parentinheritance parentinherited)
-
-         (when (or scopetypes parents)
-           (setq lscope (semantic-analyze-scoped-tags scopetypes tmpscope))
-           (oset tmpscope scope lscope))
-         (oset tmpscope fullscope (append scopetypes lscope parents))
-         ))
+       (save-excursion
+         ;; If TYPE has a position, go there and get the scope.
+         (semantic-go-to-tag type)
+
+         ;; We need to make a mini scope, and only include the misc bits
+         ;; that will help in finding the parent.  We don't really need
+         ;; to do any of the stuff related to variables and what-not.
+         (setq tmpscope (semantic-scope-cache "mini"))
+         (let* ( ;; Step 1:
+                (scopetypes (cons type (semantic-analyze-scoped-types (point))))
+                (parents (semantic-analyze-scope-nested-tags (point) scopetypes))
+                ;;(parentinherited (semantic-analyze-scope-lineage-tags parents scopetypes))
+                (lscope nil)
+                )
+           (oset tmpscope scopetypes scopetypes)
+           (oset tmpscope parents parents)
+           ;;(oset tmpscope parentinheritance parentinherited)
+
+           (when (or scopetypes parents)
+             (setq lscope (semantic-analyze-scoped-tags scopetypes tmpscope))
+             (oset tmpscope scope lscope))
+           (oset tmpscope fullscope (append scopetypes lscope parents))
+           )))
       ;; END creating tmpscope
 
       ;; Look up each parent one at a time.
@@ -662,10 +698,9 @@ The class returned from the scope calculation is variable
       nil ;; Don't do anything...
     (require 'semantic/db-typecache)
     (if (not point) (setq point (point)))
-    (when (interactive-p)
+    (when (called-interactively-p 'any)
       (semantic-fetch-tags)
-      (semantic-scope-reset-cache)
-      )
+      (semantic-scope-reset-cache))
     (save-excursion
       (goto-char point)
       (let* ((TAG  (semantic-current-tag))
@@ -722,18 +757,18 @@ The class returned from the scope calculation is variable
              (oset scopecache localargs localargs)
              (oset scopecache localvar localvar)
              )))
-       ;; Make sure we become dependant on the typecache.
+       ;; Make sure we become dependent on the typecache.
        (semanticdb-typecache-add-dependant scopecache)
        ;; Handy debug output.
-       (when (interactive-p)
+       (when (called-interactively-p 'any)
          (require 'eieio-datadebug)
-         (data-debug-show scopecache)
-         )
-       ;; Return ourselves
-       scopecache))))
+         (data-debug-show scopecache))
+       ;; Return ourselves, but make a clone first so that the caller
+       ;; can reset the scope cache without affecting others.
+       (clone scopecache)))))
 
 (defun semantic-scope-find (name &optional class scope-in)
-  "Find the tag with NAME, and optinal CLASS in the current SCOPE-IN.
+  "Find the tag with NAME, and optional CLASS in the current SCOPE-IN.
 Searches various elements of the scope for NAME.  Return ALL the
 hits in order, with the first tag being in the closest scope."
   (let ((scope (or scope-in (semantic-calculate-scope)))
@@ -796,7 +831,7 @@ hits in order, with the first tag being in the closest scope."
 ;;
 (defmethod semantic-analyze-show ((context semantic-scope-cache))
   "Insert CONTEXT into the current buffer in a nice way."
-  (require 'semantic-analyze)
+  (require 'semantic/analyze)
   (semantic-analyze-princ-sequence (oref context scopetypes) "-> ScopeTypes: " )
   (semantic-analyze-princ-sequence (oref context parents) "-> Parents: " )
   (semantic-analyze-princ-sequence (oref context scope) "-> Scope: " )
@@ -809,7 +844,6 @@ hits in order, with the first tag being in the closest scope."
 
 ;; Local variables:
 ;; generated-autoload-file: "loaddefs.el"
-;; generated-autoload-feature: semantic/loaddefs
 ;; generated-autoload-load-name: "semantic/scope"
 ;; End: