Re: I released the refactoring tool

Eric Ludlam <[email protected]> Sun, 15 Feb 2015 11:27:35 -0500
Newsgroups gmane.emacs.cedet
Message-ID <[email protected]>
Hi Tu,

I've started digging into srefactor to see how I can help.  Refactoring 
tools were always my end goal for CEDET so I'd love to see this become 
successful.

Do you have any automated or semi-automated tests?  I was going to add 
some based on your pastebin so I could figure out what the problems with 
SRecode is.  I also wanted to make SRecode optional in srefactor so it 
would be easier to start building toward using it.

I noticed that when selecting a file to generate into, I couldn't 
complete on file names that already exist.  I suspect this is because I 
don't use projectile?

Once I got the basic use of SRecode working, I found that the 
performance was very similar (perceptually).  After getting a simple 
unit test framework up and running, here are my timing results:

Elapsed Time Srecode: 1.030428
Elapsed Time Gold: 0.801937

so very close.

While adapting for SRecode, I only updated the item for 
function-implementation, figuring I could start small.  I really like 
your notion for initial content based on return type.  Very nice.  You 
also identified that there is no utility in semantic for calculating a 
fully qualified name.  There are some one-offs around, so this seems 
like something to improve in semantic.

I've attached a bunch of patches for what I was able to assemble.  A 
couple might be handy for you the rest is to just share what I'm up to.

Note that the "test" doesn't actually have tests that check anything. 
It just batch runs the utility.  There are a bunch of utilities in the 
CEDET test suite for checking one batch of tags against another that 
would be more helpful here.  The CEDET suite will insert a bunch of 
tags, then parse the buffer, and make sure the end result is the same. 
For now I was just checking the output to see what I need to fix in srecode.

I hope this helps.
Eric

------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/

_______________________________________________
Cedet-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/cedet-devel
0001-Require-recentf.patch (text/x-patch, 535 B)
>From 879789dda8668b179ee36f8e3bb8f6bbc3b383fb Mon Sep 17 00:00:00 2001
From: Eric Ludlam <[email protected]>
Date: Sun, 15 Feb 2015 10:59:07 -0500
Subject: [PATCH 1/8] Require recentf.

---
 srefactor-ui.el | 1 +
 1 file changed, 1 insertion(+)

diff --git a/srefactor-ui.el b/srefactor-ui.el
index f8af3df..e7eee5d 100644
--- a/srefactor-ui.el
+++ b/srefactor-ui.el
@@ -42,6 +42,7 @@
 ;;; Code:
 
 (require 'cl)
+(require 'recentf)
 
 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Variables
-- 
1.9.1
0002-srefactor-use-srecode-p-New.patch (text/x-patch, 3.9 KB)
>From 54488a6cfbc99715213c381a6968ecc02a464e7d Mon Sep 17 00:00:00 2001
From: Eric Ludlam <[email protected]>
Date: Sun, 15 Feb 2015 11:00:03 -0500
Subject: [PATCH 2/8] (srefactor-use-srecode-p): New (srefactor--insert-tag):
 Don't create code if srecode is being used.
 (srefactor--insert-function-implementation): If srecode option is on then use
 srecode to insert the tag.

---
 srefactor.el | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 6 deletions(-)

diff --git a/srefactor.el b/srefactor.el
index 7551417..0cedf57 100644
--- a/srefactor.el
+++ b/srefactor.el
@@ -105,6 +105,13 @@
   :group 'srefactor)
 
 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Developer Options
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar srefactor-use-srecode-p nil
+  "Use experimental SRecode tag insertion mechanism.")
+
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Commands - only one currently
 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -377,6 +384,7 @@ namespace.
     (indent-according-to-mode)
 
     ;; post content insertion based on context
+    (unless srefactor-use-srecode-p
     (unless parent-is-func-p
       (if (eq insert-type 'gen-func-impl)
           (progn
@@ -394,7 +402,8 @@ namespace.
               (indent-according-to-mode)
               (srefactor--indent-and-newline 1))
             (goto-char (line-end-position)))
-        (srefactor--maybe-insert-function-end dest-tag insert-type)))))
+        (srefactor--maybe-insert-function-end dest-tag insert-type))))
+    ))
 
 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Functions - IO
@@ -540,13 +549,43 @@ content changed."
 ;;
 
 (defun srefactor--insert-function-implementation (func-tag)
-  "Insert function implementations for FUNC-TAG, a tag that is a function."
+  "Insert function implementations for FUNC-TAG at point, a tag that is a function."
+  (forward-line 0)
+  (open-line 1)
+  (forward-line 1)
+  (if srefactor-use-srecode-p
+      ;; Try using SRecode as the mechanism for inserting a tag.
+      (let* ((copy (semantic-tag-copy func-tag))
+	     ;; (parent (semantic-tag-calculate-parent func-tag))
+	     ;; TODO - below srefactor fcn should be a part of semantic or srecode.
+	     (parentstring1 (srefactor--tag-parents-string func-tag))
+	     (parentstring (substring parentstring1 0 (- (length parentstring1) 2)))
+	     (endofinsert nil))
+	;; Copied this line from original
+	(semantic-tag-put-attribute func-tag :typemodifiers nil)
+	(semantic-tag-put-attribute func-tag :parent parentstring)
+	;; Insert the tag
+	(require 'srecode/semantic)
+	;; TODO - does it need any special dictionary entries?
+	(setq endofinsert
+	      (srecode-semantic-insert-tag 
+	       func-tag
+	       nil ;; Style
+	       (lambda (localtag)
+		 (srefactor--insert-initial-content-based-on-return-type
+		  (if (or (srefactor--tag-function-constructor copy)
+			  (srefactor--tag-function-destructor copy))
+		      ""
+		    (semantic-tag-type copy)))
+		 ) ;; Callbck for function body.
+	       ;; Dictionary entries go here.
+	       ))
+	(goto-char endofinsert)
+	(insert "\n\n")
+	)
   (let ((func-tag-name (semantic-tag-name func-tag)))
     (when (srefactor--tag-function-modifiers func-tag)
       (semantic-tag-put-attribute func-tag :typemodifiers nil))
-    (forward-line 0)
-    (open-line 1)
-    (forward-line 1)
     (insert (srefactor--tag-templates-declaration-string (srefactor--calculate-parent-tag func-tag)))
     (insert (srefactor--tag-function-string func-tag))
     (search-backward func-tag-name)
@@ -564,7 +603,7 @@ content changed."
         (c-beginning-of-statement-1)
         (re-search-forward func-tag-name)
         (replace-match ""))
-       (t)))))
+       (t))))))
 
 (defun srefactor--insert-function-pointer (tag)
   "Insert function pointer definition for TAG."
-- 
1.9.1
0003-Test-driver-to-run-srefactor-on-some-code.patch (text/x-patch, 4.4 KB)
>From 8f90fa8c9e072e47e6d2b8f03d78079358e24e3a Mon Sep 17 00:00:00 2001
From: Eric Ludlam <[email protected]>
Date: Sun, 15 Feb 2015 11:00:21 -0500
Subject: [PATCH 3/8] Test driver to run srefactor on some code.

---
 tests/srf-src-test.el | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)
 create mode 100644 tests/srf-src-test.el

diff --git a/tests/srf-src-test.el b/tests/srf-src-test.el
new file mode 100644
index 0000000..6678e7f
--- /dev/null
+++ b/tests/srf-src-test.el
@@ -0,0 +1,120 @@
+;;; srf-src-test.el --- SRefactor tests for comparing to SRecode tag insertion
+;;
+;; Copyright (C) 2015 Eric Ludlam
+;;
+;; Author: Eric Ludlam <zappo@ballista>
+;;
+;; This program 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.
+
+;; This program 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 this program.  If not, see http://www.gnu.org/licenses/.
+
+;;; Commentary:
+;;
+;; SRefactor couldn't use SRecode for inserting new code due to several
+;; problems.  This test suite is for comparing the output of the
+;; original code generator with an srecode implementaiton.
+
+;;; Code:
+
+(defvar srf-src-test-create-impl-files
+  ;;      Starting File         SRecode Version          SRefactor Gold version
+  '( ("tests/ColorSolver.hh" "tests/ColorSolver.cpp" "tests/ColorSolverGold.cpp" )
+     )
+  "List of test source files that SRefactor will be applied to.")
+
+(defun srf-src-run-tests ()
+  "Run tests of SRefactor using both the original and SRecode tag inserters."
+  (interactive)
+  ;; Run the tests for creating an implementation.
+  (dolist (TEST srf-src-test-create-impl-files)
+    (srf-src-run-create-impl-test (car TEST) (cadr TEST) (caddr TEST))
+    )
+  
+  )
+
+(defun srf-src-run-create-impl-test (start gen_into_srecode gen_into_gold)
+  "Run tests for creating an implementation from a header."
+  ;; Find and update the srecode and gold files.
+  (srf-src-find-update-src gen_into_srecode)
+  (srf-src-find-update-src gen_into_gold)
+  ;; Get the starting file updated.
+  (srf-src-find-update-src start)
+
+  ;; Run the test.
+  (let ((refactor-tag (semantic-current-tag))
+	(start_srecode (current-time))
+	end_srecode
+	start_gold end_gold)
+    
+    (setq srefactor-use-srecode-p t)
+
+    (srefactor--refactor-type (srf-src-find gen_into_srecode) refactor-tag)
+
+    (setq end_srecode (current-time)
+	  start_gold (current-time))
+
+    (setq srefactor-use-srecode-p nil)
+
+    (srf-src-find gen_into_gold)
+    (srefactor--refactor-type (srf-src-find gen_into_gold) refactor-tag)
+
+    (setq end_gold (current-time))
+
+    (message "Elapsed Time Srecode: %f" (srf-elapsed-time start_srecode end_srecode))
+    (message "Elapsed Time Gold: %f" (srf-elapsed-time start_gold end_gold))
+
+    ))
+
+
+;; Utilities
+(defvar srf-src-test-loadfrom
+  (let ((BASEDIR (file-name-directory
+		  (or load-file-name (buffer-file-name)))))
+    (file-name-directory BASEDIR))
+  "Location where this test suite came from.")
+
+(defun srf-src-find (fname)
+  "Load in a source filename."
+  (let* ((f (expand-file-name fname srf-src-test-loadfrom))
+	 (buff (find-file-noselect f)))
+    (set-buffer buff)))
+
+(defun srf-src-find-update-src (fname)
+  "Load in source fname, and update that file to prep for a test."
+  (srf-src-find fname)
+  (goto-char (point-min))
+  (cond
+   ((re-search-forward "-!-" nil t)
+    ;; We just need to go there.
+    nil)
+   
+   ((re-search-forward "// ERASE BELOW")
+    ;; We want to go there, and delete anything after this.
+    (delete-region (point) (point-max))
+    (insert "\n"))
+
+   (t
+    ;; Unsure what this is about.
+    nil)
+   )
+  )
+
+(defun srf-elapsed-time (start end)
+  "Copied from elp.el.  Was elp-elapsed-time.
+Argument START and END bound the time being calculated."
+  (+ (* (- (car end) (car start)) 65536.0)
+     (- (car (cdr end)) (car (cdr start)))
+     (/ (- (car (cdr (cdr end))) (car (cdr (cdr start)))) 1000000.0)))
+
+(provide 'srf-src-test)
+
+;;; srf-src-test.el ends here
-- 
1.9.1
0004-New.patch (text/x-patch, 450 B)
>From c3b7457f12884f344d0845942cca7a39f1382c56 Mon Sep 17 00:00:00 2001
From: Eric Ludlam <[email protected]>
Date: Sun, 15 Feb 2015 11:12:58 -0500
Subject: [PATCH 4/8] New

---
 .gitignore | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 .gitignore

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a349f6d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.elc
+*~
+#*#
\ No newline at end of file
-- 
1.9.1
0005-empty-log-message.patch (text/x-patch, 596 B)
>From a422e1f60970c08899d7a69337f90c3090ed9b5a Mon Sep 17 00:00:00 2001
From: Eric Ludlam <[email protected]>
Date: Sun, 15 Feb 2015 11:13:05 -0500
Subject: [PATCH 5/8] *** empty log message ***

---
 tests/tests/ColorSolver.cpp | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 tests/tests/ColorSolver.cpp

diff --git a/tests/tests/ColorSolver.cpp b/tests/tests/ColorSolver.cpp
new file mode 100644
index 0000000..2c5db1d
--- /dev/null
+++ b/tests/tests/ColorSolver.cpp
@@ -0,0 +1,6 @@
+// ColorSolver Implementation
+
+#include <ColorSolver.hh>
+
+// ERASE BELOW
+
-- 
1.9.1
0006-empty-log-message.patch (text/x-patch, 1.5 KB)
>From 33e4cc1836edb87d6ea59d1505e883ec64f8bef1 Mon Sep 17 00:00:00 2001
From: Eric Ludlam <[email protected]>
Date: Sun, 15 Feb 2015 11:13:08 -0500
Subject: [PATCH 6/8] *** empty log message ***

---
 tests/tests/ColorSolver.hh | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 tests/tests/ColorSolver.hh

diff --git a/tests/tests/ColorSolver.hh b/tests/tests/ColorSolver.hh
new file mode 100644
index 0000000..6f975a6
--- /dev/null
+++ b/tests/tests/ColorSolver.hh
@@ -0,0 +1,35 @@
+// Example class
+
+// (setq srefactor-use-srecode-p nil)
+// (setq srefactor-use-srecode-p t)
+
+class ColoringSolver
+{ // -!-
+private:
+    std::set<std::set<std::map<int,int>>> *color_repo;
+    std::map<int, int> color_statistics;
+ 
+    class test {
+        int test3(int a);
+        template <typename T4, typename T5>
+        class test2 {
+            T5 test5(T4 t);
+            int test4(int b);
+        };
+    };
+ 
+    void find_used_colors(Vertex& v, std::set<int>& used_colors);
+    void find_viable_colors(Vertex& v, const std::set<int>& used_colors, std::set<int>& viable_colors);
+    int get_highest_color(const std::set<int>& viable_colors);
+    int find_redundant_color(const Vertex& v, const std::set<int>& viable_color);
+    void repaint_neighbors(const Vertex& v);
+    void paint_indirect_nodes(const Vertex& v);
+    void add_new_color(Vertex& v);
+public:
+    std::vector<Vertex> vertices;
+ 
+    Answer solve();
+ 
+    ColoringSolver(){}
+    virtual ~ColoringSolver(){}
+};
-- 
1.9.1
0007-empty-log-message.patch (text/x-patch, 616 B)
>From 984d0d25a0bd239d5a089b8e26ce9e3614824cbe Mon Sep 17 00:00:00 2001
From: Eric Ludlam <[email protected]>
Date: Sun, 15 Feb 2015 11:13:13 -0500
Subject: [PATCH 7/8] *** empty log message ***

---
 tests/tests/ColorSolverGold.cpp | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 tests/tests/ColorSolverGold.cpp

diff --git a/tests/tests/ColorSolverGold.cpp b/tests/tests/ColorSolverGold.cpp
new file mode 100644
index 0000000..2c5db1d
--- /dev/null
+++ b/tests/tests/ColorSolverGold.cpp
@@ -0,0 +1,6 @@
+// ColorSolver Implementation
+
+#include <ColorSolver.hh>
+
+// ERASE BELOW
+
-- 
1.9.1
0008-Add-patch-files.patch (text/x-patch, 492 B)
>From f7953efd1d592f6074e925f872338524b89b5359 Mon Sep 17 00:00:00 2001
From: Eric Ludlam <[email protected]>
Date: Sun, 15 Feb 2015 11:15:14 -0500
Subject: [PATCH 8/8] Add patch files

---
 .gitignore | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index a349f6d..76c60a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 *.elc
 *~
-#*#
\ No newline at end of file
+.#*
+[0-9][0-9][0-9][0-9]-*
\ No newline at end of file
-- 
1.9.1