Commits

Anonymous committed b5724d7

Changing M-O to C-O

Comments (0)

Files changed (11)

 M-V        Move refactoring
 M-I        Inline local variable
 
-M-O        Organize imports
+C-O        Organize imports
 =========  ======================
 
 
 M-M            extract method
 M-V            move refactoring
 M-I            inline local variable
+C-O            organize imports
 =============  ==========================
 
 Have a look at `docs/overview.txt`_ file for an overview of rope's features.
 during one action we can revert back.
 
 
+Moving Fields/Methods
+=====================
+
+* How to specify the destination field?
+
+  The problem is move refactoring takes a resource as its
+  destination but surely we need something to indicate destination fields.
+
+* How tell that a pyname is a class attribute?
+
+  * An attribute should be defined in a class or a method in a class
+  * The holding class for a pyname should consider it as one of its
+    attributes
+
+* Moving defined objects
+
+  * If self is used renaming it and passing it as a second argument?
+  * Moving used imports
+
+Move refactoring should support moving:
+
+=======================  =============
+source                   destination
+=======================  =============
+module                   module
+global class/function    module
+class fields/methods     attribute
+static functions         class
+=======================  =============
+
+The problem of destination might be solved by passing a `PyName`
+or a `PyObject` instead of a `Resource`.  Maybe we can take a
+class as the destination for moving fields and methods instead
+of an attribute.
+
+Maybe we can have separate methods for moving each of above
+groups.
+
+move_module(resource, resource)
+move_global(pyobject, resource)
+move_attribute(pyobject, pyobject)
+
+
 Dyanmic Type Inference Issues
 =============================
 
 we can perform the actual refactoring.  The challenge here is that we
 should consider inheritance relations, too.
 
+Among `PyName` classes `AssignedName`, `ParameterName` and
+`ImportedName` might have more than one object.  And I believe
+the main place to change is `StatementEvaluator` that might
+return a list of pynames in ``${attribute_accesses}.name``
+where `attribute_accessses` might result in more than one kind
+of pyname.  This implies that `get_pyname_at` might return a list
+of pynames.
+
+`objectinfer` should be changed to find all of the objects that can
+be inferred.
+
 
 Which Is Right? Type Or Object Inference
 ========================================
 information about the methods defined in these derived classes.
 
 
-Getting Buried Under Layers
-===========================
-
-Starting from `rope.pycore` module, there are many layers that are
-hidden beneath it.  Most of unit tests only test `PyCore` directly and
-other parts are tested indirectly through many layers that lead to
-`PyCore`.  I guess this is a bad sign.  Maybe I should put more time
-in making each layer more testable and independant of other layers.
-
-
 Builtin Types And Functions
 ===========================
 
 Unfortunately `Tk` has problems for handling multi-key keyboard
 shortcuts.  We can develop another independant keybinding system that
 uses `Tk` to solve these problems.
+
+
+A Good Keybinding
+-----------------
+
+Make a good emacs-ish keybinding.
 * Introduce redirection
 
 
+* Encapsulate field
+
+
+* Change method signature
+
+  * Add parameter
+  * Remove parameter
+  * Reorder
+
+
+* Moving fields/methods to attribute classes
+
+
+* Sorting imports; standard, third party, project
+
+
+* Removing imports from the same module
+
+
 * Enhancing module running
 
   * Showing running status in the GUI
   * Running last run
 
 
-* Change method signature
-
-  * Add parameter
-  * Remove parameter
-  * Reorder
-
-
-* Sorting imports; standard, third party, project
+* Running unit tests view
 
 
 * Inline method
 
 
-* Removing imports from the same module
-
-
-* Running unit tests view
-
-
-* Encapsulate field
-
-
-* Moving fields/methods to attribute classes
-
-
 > Public Release 0.3m5 : October 15, 2006
 
 

docs/workingon.txt

-Refactoring
+Exploration
 ===========
 
-- Changing move refactoring dialog to take module name
-- Folder destinations and move refactorings
+* Implicit interfaces sprint
+* Unit test view
+* Move field
+
+* Adding ``add_method(scope, method)``
+* Adding ``add_statement(method, statement)``
+
+
+Before ``0.3m5``
+================
+
+* ``overview.txt``
+* ``README.txt``
+* homepage
 
 
 Remaining Stories
 =================
 
 * Reporting unhandled exceptions as error dialogs in the GUI
-* Better move dialog; complete modules names; use editor._CompletionListHandle
+* Better move dialog; complete modules names; use `editor._CompletionListHandle`
+* Moving/renaming current module
 * Showing initial name in rename dialogs
 * Adding ``overview.txt``, ``README.txt``, ``tutorial.txt`` and
   ``COPYING`` to help menu; Adding readonly mode?

rope/refactor/__init__.py

 from rope.refactor.inline import InlineRefactoring
 
 
-class Refactoring(object):
-    pass
-
-
-class PythonRefactoring(Refactoring):
+class PythonRefactoring(object):
 
     def __init__(self, pycore):
         self.pycore = pycore
             self.refactoring._add_and_commit_changes(changes)
     
 
-class NoRefactoring(Refactoring):
+class NoRefactoring(object):
     pass
 
 

rope/refactor/move.py

                                            pyname, old_name, new_name)
         self.new_import = self.import_tools.get_import_for_module(
             self.pycore.resource_to_pyobject(self.destination))
+        scope = pyname.get_object().get_scope()
 
     def _check_exceptional_conditions(self):
         if self.old_pyname is None or \
         pymodule, has_changed = self._rename_in_module(pymodule, self.new_name)
         if has_changed:
             uses_moving = True
-        source = self._get_moved_moving_source(pymodule.source_code)
+        source = self._get_moved_moving_source(pymodule)
         if uses_moving:
             pymodule = self.pycore.get_string_module(source, self.source)
             # Adding new import
         
         changes.add_change(ChangeFileContents(self.source, source))
 
-    def _get_moved_moving_source(self, source):
-        lines = self.pycore.resource_to_pyobject(self.source).lines
+    def _get_moved_moving_source(self, pymodule):
+        source = pymodule.source_code
+        lines = pymodule.lines
         scope = self.old_pyname.get_object().get_scope()
         start = lines.get_line_start(scope.get_start())
         end = lines.get_line_end(scope.get_end())
     
     def _change_moving_module(self, changes):
         if not self.source.is_folder():
+            is_changed = False
             pymodule = self.pycore.resource_to_pyobject(self.source)
             source = self.import_tools.transform_relative_imports_to_absolute(pymodule)
             if source is not None:
-                changes.add_change(ChangeFileContents(self.source,
-                                                      source))
+                pymodule = self.pycore.get_string_module(source, self.source)
+                is_changed = True
+            source = self._change_occurances_in_module(pymodule)
+            if source is not None:
+                is_changed = True
+            else:
+                source = pymodule.source_code
+            if is_changed:
+                changes.add_change(ChangeFileContents(self.source, source))
         changes.add_change(MoveResource(self.source,
                                         self.destination.get_path()))
 
         for module in self.pycore.get_python_files():
             if module in (self.source, self.destination):
                 continue
-            is_changed = False
-            should_import = False
             pymodule = self.pycore.resource_to_pyobject(module)
-            pymodule, has_changed = self._rename_in_module(pymodule, self.new_name, imports=True)
-            if has_changed:
-                is_changed = True
-            pymodule, has_changed = self._remove_old_pyname_imports(pymodule)
-            if has_changed:
-                should_import = True
-                is_changed = True
-            if should_import:
-                source = self._add_imports_to_module(pymodule, [self.new_import])
-            else:
-                source = pymodule.source_code
-            if is_changed:
+            source = self._change_occurances_in_module(pymodule)
+            if source is not None:
                 changes.add_change(ChangeFileContents(module, source))
-    
+
+    def _change_occurances_in_module(self, pymodule):
+        is_changed = False
+        should_import = False
+        pymodule, has_changed = self._rename_in_module(pymodule, self.new_name,
+                                                       imports=True)
+        if has_changed:
+            is_changed = True
+        pymodule, has_changed = self._remove_old_pyname_imports(pymodule)
+        if has_changed:
+            should_import = True
+            is_changed = True
+        if should_import:
+            source = self._add_imports_to_module(pymodule, [self.new_import])
+        else:
+            source = pymodule.source_code
+        if is_changed:
+            return source
+

rope/refactor/occurances.py

 import re
 
 import rope.codeanalyze
-import rope.pynames
-import rope.pyobjects
-import rope.refactor.occurances
 
 
 class OccurrenceFinder(object):
     
     def find_occurances(self, resource=None, pymodule=None):
         source_code = self._get_source(resource, pymodule)
-        name_finder_creator = rope.refactor.occurances.\
-                              _LazyNameFinderCreator(self.pycore,
+        name_finder_creator = _LazyNameFinderCreator(self.pycore,
                                                      resource, pymodule)
         word_finder = rope.codeanalyze.WordRangeFinder(source_code)
         for match in self.pattern.finditer(source_code):

rope/ui/refactor.py

         toplevel.title('Choose Destination Module')
         tree_handle = _ModuleViewHandle(core.get_open_project(), toplevel, do_select)
         tree_view = TreeView(toplevel, tree_handle, title='Destination Module')
-        tree_view.add_entry(context.get_core().project.get_root_folder())
+        for folder in project.get_pycore().get_source_folders():
+            tree_view.add_entry(folder)
         tree_view.list.focus_set()
         toplevel.grab_set()
 
                             MenuAddress(['Refactor', 'Transform Module to Package'], 't', 1), 
                             ['python']))
 actions.append(SimpleAction('Organize Imports', 
-                            ConfirmAllEditorsAreSaved(organize_imports), 'M-O',
+                            ConfirmAllEditorsAreSaved(organize_imports), 'C-O',
                             MenuAddress(['Refactor', 'Organize Imports'], 'o', 2), ['python']))
 actions.append(SimpleAction('Expand Star Imports', 
                             ConfirmAllEditorsAreSaved(expand_star_imports), None,

ropetest/refactor/movetest.py

         self.assertEquals('pkg2/pkg/mod5.py', self.mod5.get_path())
         self.assertEquals('import pkg2.pkg.mod4\nprint pkg2.pkg.mod4', self.mod1.read())
 
+    def test_moving_modules_with_self_imports(self):
+        self.mod1.write('import mod1\nprint mod1\n')
+        self.mod2.write('import mod1\n')
+        self.refactoring.move(self.mod2, self.mod2.read().index('mod1') + 1, self.pkg)
+        self.assertEquals('import pkg.mod1\nprint pkg.mod1\n', self.mod1.read())
+    
+    # TODO: moving fields
+    def xxx_test_moving_fields(self):
+        a_class = 'class A(object):\n' \
+                  '    def __init__(self):\n' \
+                  '        self.b = B()\n' \
+                  '        self.attr = 1\n'
+        b_class = 'class B(object):\n    pass\n'
+        self.mod1.write(a_class + b_class)
+        self.refactoring.move(self.mod1, self.mod1.read().index('attr') + 1, 'b')
+        
+        a_class2 = 'class A(object):\n' \
+                   '    def __init__(self):\n' \
+                   '        self.b = B()\n' \
+                   '        self.b.attr = 1\n'
+        self.assertEquals(a_class2 + b_class, self.mod1.read())
+
 
 if __name__ == '__main__':
     unittest.main()

ropetest/refactor/renametest.py

         refactored = self.do_local_rename(code, code.rfind('param') + 1, 'new_param')
         self.assertEquals('def a_func(new_param):\n    print new_param\n'
                           'a_func  (new_param=hey)\n', refactored)
+
+
+if __name__ == '__main__':
+    unittest.main()

ropetest/runmodtest.py

         self.project.get_root_folder().create_folder('test')
         file_path = 'test/test.py'
         self.make_sample_python_file(file_path,
-                                     "def get_text():" +
-                                     "\n    import sample\n    sample.f()\n    return'run'\n")
+                                     "def get_text():\n"
+                                     "    import sample\n    sample.f()\n    return'run'\n")
         file_resource = self.project.get_resource(file_path)
         runner = self.pycore.run_module(file_resource)
         runner.wait_process()