├── LICENSE ├── README.md ├── doc └── refactoring-toolbox.txt ├── playground.php └── plugin └── php-refactoring-toolbox.vim /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Pierrick Charron 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VIM Php Refactoring Toolbox 2 | 3 | [![License: MIT](https://img.shields.io/github/license/adoy/vim-php-refactoring-toolbox)](https://opensource.org/licenses/MIT) 4 | 5 | PHP Refactoring Toolbox for VIM 6 | 7 | * Rename Local Variable 8 | * Rename Class Variable 9 | * Rename Method 10 | * Extract Use 11 | * Extract Const 12 | * Extract Class Property 13 | * Extract Method 14 | * Create Property 15 | * Detect Unused Use Statements 16 | * Align Assigns 17 | * Create setters and getters 18 | * Document all code 19 | 20 | ## Installation 21 | 22 | * [vim-plug](https://github.com/junegunn/vim-plug): `Plug 'adoy/vim-php-refactoring-toolbox'` 23 | * [vundle](https://github.com/gmarik/Vundle.vim): `Plugin 'adoy/vim-php-refactoring-toolbox'` 24 | * [pathogen](https://github.com/tpope/vim-pathogen): `git clone https://github.com/adoy/vim-php-refactoring-toolbox.git ~/.vim/bundle/` 25 | * or just copy the `plugin/php-refactoring-toolbox.vim` in your `~/.vim/plugin` folder 26 | 27 | 28 | If you want to disable the default mapping just add this line in your `~/.vimrc` file 29 | 30 | ``` 31 | let g:vim_php_refactoring_use_default_mapping = 0 32 | ``` 33 | 34 | If you want to disable the user validation at the getter/setter creation, just add this line in your `~/.vimrc` file 35 | 36 | ``` 37 | let g:vim_php_refactoring_auto_validate_sg = 1 38 | ``` 39 | 40 | If you want to disable the user validation at getter only creation, just add this line in your `~/.vimrc` file 41 | 42 | ``` 43 | let g:vim_php_refactoring_auto_validate_g = 1 44 | ``` 45 | 46 | If you want to disable the user validation for all rename features, just add this line in your `~/.vimrc` file 47 | 48 | ``` 49 | let g:vim_php_refactoring_auto_validate_rename = 1 50 | ``` 51 | 52 | If you want to disable the user validation for the visibility (private/public) add this line in your `~/.vimrc` file 53 | ``` 54 | let g:vim_php_refactoring_auto_validate_visibility = 1 55 | ``` 56 | 57 | To change the default visibility add one/both of those lines in your `~/.vimrc` file 58 | ``` 59 | let g:vim_php_refactoring_default_property_visibility = 'private' 60 | let g:vim_php_refactoring_default_method_visibility = 'private' 61 | ``` 62 | 63 | To enable fluent setters add either of these lines to your `~/.vimrc` file 64 | ``` 65 | " default is 0 -- disabled 66 | 67 | " to enable for all setters 68 | let g:vim_php_refactoring_make_setter_fluent = 1 69 | 70 | " to enable but be prompted when creating the setter 71 | let g:vim_php_refactoring_make_setter_fluent = 2 72 | ``` 73 | 74 | 75 | ## Default Mappings 76 | 77 | nnoremap rlv :call PhpRenameLocalVariable() 78 | nnoremap rcv :call PhpRenameClassVariable() 79 | nnoremap rm :call PhpRenameMethod() 80 | nnoremap eu :call PhpExtractUse() 81 | vnoremap ec :call PhpExtractConst() 82 | nnoremap ep :call PhpExtractClassProperty() 83 | vnoremap em :call PhpExtractMethod() 84 | nnoremap np :call PhpCreateProperty() 85 | nnoremap du :call PhpDetectUnusedUseStatements() 86 | vnoremap == :call PhpAlignAssigns() 87 | nnoremap sg :call PhpCreateSettersAndGetters() 88 | nnoremap cog :call PhpCreateGetters() 89 | nnoremap da :call PhpDocAll() 90 | 91 | ## Playground.php 92 | 93 | You'll find in this project a `playground.php` file. You can use this file to start playing with this refactoring plugin. 94 | 95 | ## Examples 96 | 97 | ↑ Is the position of your cursor 98 | 99 | ### Rename Local Variable 100 | 101 | ``` php 102 | rlv` in normal mode, specify the new `$name` 109 | 110 | ``` php 111 | foobar = $name; 125 | } 126 | public function sayHello() { 127 | echo $this->foobar; 128 | } ↑ 129 | } 130 | ``` 131 | 132 | `rcv` in normal mode, specify the new `$name` 133 | 134 | ``` php 135 | name = $name; 140 | } 141 | public function sayHello() { 142 | echo $this->name; 143 | } 144 | } 145 | ``` 146 | 147 | ### Rename method 148 | 149 | ``` php 150 | sayHello(); 154 | } ↑ 155 | } 156 | ``` 157 | 158 | `rm` in normal mode, specify the new method name 159 | 160 | ``` php 161 | newMethodName(); 165 | } ↑ 166 | } 167 | ``` 168 | 169 | ### Extract Use Statement 170 | 171 | ``` php 172 | eu` in normal mode 179 | 180 | ``` php 181 | ep` in normal mode will extract the local variable and create a property inside the current class. 202 | 203 | ``` php 204 | realpath = $path; 210 | } ↑ 211 | } 212 | ``` 213 | 214 | ### Extract Method 215 | 216 | ``` php 217 | em`. 231 | You'll be prompted for a method name. Enter a method name and press enter 232 | 233 | ``` php 234 | prepareSentence($firstName); 239 | echo $sentence; 240 | } 241 | 242 | private function prepareSentence($firstName) 243 | { 244 | $sentence = 'Hello'; 245 | if ($firstName) { 246 | $sentence .= ' ' . $firstName; 247 | } 248 | return $sentence; 249 | } 250 | } 251 | ``` 252 | 253 | ### Create Property 254 | 255 | `np` will create a new property in your current class. 256 | 257 | ### Detect unused "use" statements 258 | 259 | `du` will detect all unused "use" statements in your code so that you can remove them. 260 | 261 | ### Align assignments 262 | 263 | ``` php 264 | ==` 272 | 273 | ``` php 274 | sg` and you'll be prompted if you want to create setters and getters for existing properties and if you want to make the setter fluent. 292 | 293 | ``` php 294 | bar = $bar; 302 | 303 | return $this; // If you opted for a fluent setter at the prompt. 304 | } 305 | 306 | public function getBar() 307 | { 308 | return $this->bar; 309 | } 310 | } 311 | ``` 312 | 313 | ### Create only getters 314 | 315 | ``` php 316 | cog` and you will be prompted if you want only getters for existing properties 324 | 325 | ``` php 326 | bar; 334 | } 335 | } 336 | ``` 337 | 338 | ### Document all 339 | 340 | `da` will call your documentation plugin (by default Php Documentor for vim https://github.com/tobyS/pdv) for every uncommented classes, methods, functions and properties. 341 | 342 | 343 | -------------------------------------------------------------------------------- /doc/refactoring-toolbox.txt: -------------------------------------------------------------------------------- 1 | *refactoring-toolbox* 2 | 3 | __________ _____ __ .__ ___________ .__ ___. 4 | \______ \ _____/ ____\____ _____/ |_ ___________|__| ____ ____ \__ ___/___ ____ | |\_ |__ _______ ___ 5 | | _// __ \ __\\__ \ _/ ___\ __\/ _ \_ __ \ |/ \ / ___\ | | / _ \ / _ \| | | __ \ / _ \ \/ / 6 | | | \ ___/| | / __ \\ \___| | ( <_> ) | \/ | | \/ /_/ > | |( <_> | <_> ) |_| \_\ ( <_> > < 7 | |____|_ /\___ >__| (____ /\___ >__| \____/|__| |__|___| /\___ / |____| \____/ \____/|____/___ /\____/__/\_ \ 8 | \/ \/ \/ \/ \//_____/ \/ \/ 9 | 10 | =============================================================================== 11 | CONTENTS *refactoring-toolbox-contents* 12 | 13 | 1. Intro........................................|refactoring-toolbox-intro| 14 | 2. Mappings.....................................|refactoring-toolbox-mappings| 15 | 2. Examples.....................................|refactoring-toolbox-examples| 16 | 2. Playground...................................|refactoring-toolbox-playground| 17 | 18 | =============================================================================== 19 | INTRO *refactoring-toolbox-intro* 20 | 21 | Vim PHP Refactoring ToolBox. 22 | 23 | A set of commands which help you to refactor PHP code. 24 | 25 | =============================================================================== 26 | Default Mappings *refactoring-toolbox-mappings* 27 | 28 | nnoremap rlv :call PhpRenameLocalVariable() 29 | nnoremap rcv :call PhpRenameClassVariable() 30 | nnoremap rm :call PhpRenameMethod() 31 | nnoremap eu :call PhpExtractUse() 32 | vnoremap ec :call PhpExtractConst() 33 | nnoremap ep :call PhpExtractClassProperty() 34 | vnoremap em :call PhpExtractMethod() 35 | nnoremap np :call PhpCreateProperty() 36 | nnoremap du :call PhpDetectUnusedUseStatements() 37 | vnoremap == :call PhpAlignAssigns() 38 | nnoremap sg :call PhpCreateSettersAndGetters() 39 | nnoremap da :call PhpDocAll() 40 | 41 | =============================================================================== 42 | Examples *refactoring-toolbox-examples* 43 | 44 | 1. Rename Local Variable........................................|rename-local-variable| 45 | 2. Rename Class Variable........................................|rename-class-variable| 46 | 3. Rename Method................................................|rename-method| 47 | 4. Extract Use Statement........................................|extract-use-statement| 48 | 5. Extract Class Property.......................................|extract-class-property| 49 | 6. Extract Method...............................................|extract-method| 50 | 7. Create Property..............................................|create-property| 51 | 8. Detect Unused Use Statements.................................|detect-unused-use| 52 | 9. Align assignments............................................|align-assignments| 53 | 10. Create Setters and Getters..................................|create-set-get| 54 | 11. Document all................................................|document-all| 55 | 56 | Note: ↑ Is the position of your cursor 57 | 58 | =============================================================================== 59 | Rename Local Variable *rename-local-variable* 60 | 61 | rlv in normal mode, specify the new $name 67 | 68 | foobar = $name; 81 | } 82 | public function sayHello() { 83 | echo $this->foobar; 84 | } ↑ 85 | } 86 | 87 | rcv in normal mode, specify the new $name 88 | 89 | name = $name; 94 | } 95 | public function sayHello() { 96 | echo $this->name; 97 | } 98 | } 99 | 100 | =============================================================================== 101 | Rename method *rename-method* 102 | 103 | sayHello(); 107 | } ↑ 108 | } 109 | 110 | rm in normal mode, specify the new method name 111 | 112 | newMethodName(); 116 | } ↑ 117 | } 118 | 119 | =============================================================================== 120 | Extract Use Statement *extract-use-statement* 121 | 122 | eu in normal mode 128 | 129 | ep in normal mode will extract the local variable and create a property inside the current class. 148 | 149 | realpath = $path; 155 | } ↑ 156 | } 157 | 158 | =============================================================================== 159 | Extract Method *extract-method* 160 | 161 | em. You'll be prompted for a method name. Enter a method name and press enter 174 | 175 | prepareSentence($firstName); 180 | echo $sentence; 181 | } 182 | 183 | private function prepareSentence($firstName) 184 | { 185 | $sentence = 'Hello'; 186 | if ($firstName) { 187 | $sentence .= ' ' . $firstName; 188 | } 189 | return $sentence; 190 | } 191 | } 192 | 193 | =============================================================================== 194 | Create Property *create-property* 195 | 196 | np will create a new property in your current class. 197 | 198 | =============================================================================== 199 | Detect unused "use" statements *detect-unused-use* 200 | 201 | 202 | du will detect all unused "use" statements in your code so that you can remove them. 203 | 204 | =============================================================================== 205 | Align assignments *align-assignments* 206 | 207 | 208 | == 215 | 216 | sg` and you'll be prompted if you want to create setters and getters for existing properties and if you want to make the setter fluent. 233 | 234 | bar = $bar; 242 | } 243 | 244 | public function getBar() 245 | { 246 | return $this->bar; 247 | } 248 | } 249 | 250 | =============================================================================== 251 | Document all *document-all* 252 | 253 | da will call your documentation plugin (by default Php Documentor for vim https://github.com/tobyS/pdv) for every uncommented classes, methods, functions and properties. 254 | 255 | =============================================================================== 256 | Playground *refactoring-toolbox-playground* 257 | 258 | Here you have some code within you can try some of the available tools: 259 | 260 | rlv 269 | * to rename a function local variable 270 | */ 271 | public function testRenameLocalVariable($renameMe) 272 | { 273 | $renameMe = 'renameMe will be renamed'; 274 | $renameMeAlso = $renameMe; 275 | $this->renameMe = 'If will be renamed in the next test'; 276 | } 277 | /** 278 | * Place your cursor on a class variable and press rcv 279 | * to rename a property (class variable) 280 | */ 281 | public function testRenameClassVariable($renameMe) 282 | { 283 | $this->renameMe = 'RenameMe rename every usage of this property in the current class'; 284 | $renameMe = 'I\'m not renamed'; 285 | } 286 | /** 287 | * Place your cursor on a method name and press rm 288 | * to rename a method 289 | */ 290 | public function testRenameMethod() 291 | { 292 | $this->testRenameMethod(); 293 | } 294 | /** 295 | * Place your cursor on a Fully qualified class name and press eu 296 | * to create an alias and place the new Use statement on top of the file 297 | */ 298 | public function testExtractUse(\Fully\Qualified\Classname $obj) 299 | { 300 | if (!$obj instanceof \Fully\Qualified\Classname) { 301 | Throw new Exception('$obj is not a \Fully\Qualified\Classname'); 302 | } 303 | return new \Fully\Qualified\AnOtherClassname; 304 | } 305 | /** 306 | * Select the content you want to place in the content with the visual mode 307 | * (you could use viw on int or va' on string) 308 | * and then press ec to create a constant and replace every occurence of this 309 | * by the constant usage 310 | */ 311 | public function testExtractConst() 312 | { 313 | $dix = 1001; 314 | $string = 'FOOBAR'; 315 | } 316 | /** 317 | * Place your cursor on the "localVariableWanabeAClassVariable" variable 318 | * and press ep to promote this variable as class property 319 | */ 320 | public function testExtractClassProperty($newval) 321 | { 322 | $localVariableWanabeAClassVariable = $newval; 323 | } 324 | /** 325 | * Select different block of code and extract it to different methods using 326 | * em 327 | */ 328 | public function testExtractMethod($message) 329 | { 330 | // Make a very cool wave with the message 331 | for ($i = 0; $i < strlen($message); $i++) { 332 | $message[$i] = $i % 2 ? strtoupper($message[$i]) : strtolower($message[$i]); 333 | } 334 | // Put the message in a fancy box 335 | $borderTopAndBottom = '+' . str_repeat('=', strlen($message)+2) . '+'; 336 | $newMessage = $borderTopAndBottom . PHP_EOL; 337 | $newMessage .= '| ' . $message . ' |' . PHP_EOL; 338 | $newMessage .= $borderTopAndBottom . PHP_EOL; 339 | return $newMessage; 340 | } 341 | /** 342 | * Press np to create a property 343 | */ 344 | public function testCreateNewProperty() 345 | { 346 | $this->notCreated; 347 | } 348 | /** 349 | * Press du to detect unused use statements 350 | */ 351 | public function testDetectUnusedStatements() 352 | { 353 | new Lover; 354 | } 355 | /** 356 | * Select the inner function block 357 | * and press == to align all assignements 358 | */ 359 | public function testAlignAssigns() 360 | { 361 | $oneVar = 'Foo'; 362 | $anOtherVar = 'Bar'; 363 | $oneVar += 'Baz'; 364 | } 365 | } 366 | 367 | 368 | -------------------------------------------------------------------------------- /playground.php: -------------------------------------------------------------------------------- 1 | rlv 14 | * to rename a function local variable 15 | */ 16 | public function testRenameLocalVariable($renameMe) 17 | { 18 | $renameMe = 'renameMe will be renamed'; 19 | $renameMeAlso = $renameMe; 20 | $this->renameMe = 'I will be renamed in the next test'; 21 | } 22 | 23 | /** 24 | * Place your cursor on a class variable and press rcv 25 | * to rename a property (class variable) 26 | */ 27 | public function testRenameClassVariable($renameMe) 28 | { 29 | $this->renameMe = 'RenameMe rename every usage of this property in the current class'; 30 | $renameMe = 'I\'m not renamed'; 31 | } 32 | 33 | /** 34 | * Place your cursor on a method name and press rm 35 | * to rename a method 36 | */ 37 | public function testRenameMethod() 38 | { 39 | $this->testRenameMethod(); 40 | } 41 | 42 | /** 43 | * Place your cursor on a Fully qualified class name and press eu 44 | * to create an alias and place the new Use statement on top of the file 45 | */ 46 | public function testExtractUse(\Fully\Qualified\Classname $obj) 47 | { 48 | if (!$obj instanceof \Fully\Qualified\Classname) { 49 | Throw new Exception('$obj is not a \Fully\Qualified\Classname'); 50 | } 51 | return new \Fully\Qualified\AnOtherClassname; 52 | } 53 | 54 | /** 55 | * Select the content you want to place in the content with the visual mode 56 | * (you could use viw on int or va' on string) 57 | * and then press ec to create a constant and replace every occurence of this 58 | * by the constant usage 59 | */ 60 | public function testExtractConst() 61 | { 62 | $dix = 1001; 63 | $string = 'FOOBAR'; 64 | } 65 | 66 | /** 67 | * Place your cursor on the "localVariableWanabeAClassVariable" variable 68 | * and press ep to promote this variable as class property 69 | */ 70 | public function testExtractClassProperty($newval) 71 | { 72 | $localVariableWanabeAClassVariable = $newval; 73 | } 74 | 75 | /** 76 | * Select different block of code and extract it to different methods using 77 | * em 78 | */ 79 | public function testExtractMethod($message) 80 | { 81 | // Make a very cool wave with the message 82 | for ($i = 0; $i < strlen($message); $i++) { 83 | $message[$i] = $i % 2 ? strtoupper($message[$i]) : strtolower($message[$i]); 84 | } 85 | 86 | // Put the message in a fancy box 87 | $borderTopAndBottom = '+' . str_repeat('=', strlen($message)+2) . '+'; 88 | $newMessage = $borderTopAndBottom . PHP_EOL; 89 | $newMessage .= '| ' . $message . ' |' . PHP_EOL; 90 | $newMessage .= $borderTopAndBottom . PHP_EOL; 91 | 92 | return $newMessage; 93 | } 94 | 95 | /** 96 | * Press np to create a property 97 | */ 98 | public function testCreateNewProperty() 99 | { 100 | $this->notCreated; 101 | } 102 | 103 | /** 104 | * Press du to detect unused use statements 105 | */ 106 | public function testDetectUnusedStatements() 107 | { 108 | new Lover; 109 | } 110 | 111 | /** 112 | * Select the inner function block 113 | * and press == to align all assignements 114 | */ 115 | public function testAlignAssigns() 116 | { 117 | $oneVar = 'Foo'; 118 | $anOtherVar = 'Bar'; 119 | $oneVar += 'Baz'; 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /plugin/php-refactoring-toolbox.vim: -------------------------------------------------------------------------------- 1 | " 2 | " VIM PHP Refactoring Toolbox 3 | " 4 | " Maintainer: Pierrick Charron 5 | " URL: https://github.com/adoy/vim-php-refactoring-toolbox 6 | " License: MIT 7 | " Version: 1.0.3 8 | " 9 | 10 | if exists('g:vim_php_refactoring_loaded') 11 | finish 12 | endif 13 | let g:vim_php_refactoring_loaded = 1 14 | 15 | " Config {{{ 16 | " VIM function to call to document the current line 17 | if !exists('g:vim_php_refactoring_phpdoc') 18 | let g:vim_php_refactoring_phpdoc = 'PhpDoc' 19 | endif 20 | 21 | if !exists('g:vim_php_refactoring_use_default_mapping') 22 | let g:vim_php_refactoring_use_default_mapping = 1 23 | endif 24 | 25 | if !exists('g:vim_php_refactoring_auto_validate') 26 | let g:vim_php_refactoring_auto_validate = 0 27 | endif 28 | 29 | if !exists('g:vim_php_refactoring_auto_validate_sg') 30 | let g:vim_php_refactoring_auto_validate_sg = g:vim_php_refactoring_auto_validate 31 | endif 32 | 33 | if !exists('g:vim_php_refactoring_auto_validate_g') 34 | let g:vim_php_refactoring_auto_validate_g = g:vim_php_refactoring_auto_validate 35 | endif 36 | 37 | if !exists('g:vim_php_refactoring_auto_validate_rename') 38 | let g:vim_php_refactoring_auto_validate_rename = g:vim_php_refactoring_auto_validate 39 | endif 40 | 41 | if !exists('g:vim_php_refactoring_auto_validate_visibility') 42 | let g:vim_php_refactoring_auto_validate_visibility = g:vim_php_refactoring_auto_validate 43 | endif 44 | 45 | if !exists('g:vim_php_refactoring_default_property_visibility') 46 | let g:vim_php_refactoring_default_property_visibility = 'private' 47 | endif 48 | 49 | if !exists('g:vim_php_refactoring_default_method_visibility') 50 | let g:vim_php_refactoring_default_method_visibility = 'private' 51 | endif 52 | 53 | if !exists('g:vim_php_refactoring_make_setter_fluent') 54 | let g:vim_php_refactoring_make_setter_fluent = 0 55 | endif 56 | " }}} 57 | 58 | " Refactoring mapping {{{ 59 | if g:vim_php_refactoring_use_default_mapping == 1 60 | nnoremap rlv :call PhpRenameLocalVariable() 61 | nnoremap rcv :call PhpRenameClassVariable() 62 | nnoremap eu :call PhpExtractUse() 63 | nnoremap rm :call PhpRenameMethod() 64 | vnoremap ec :call PhpExtractConst() 65 | nnoremap ep :call PhpExtractClassProperty() 66 | vnoremap em :call PhpExtractMethod() 67 | nnoremap np :call PhpCreateProperty() 68 | nnoremap du :call PhpDetectUnusedUseStatements() 69 | vnoremap == :call PhpAlignAssigns() 70 | nnoremap sg :call PhpCreateSettersAndGetters() 71 | nnoremap cog :call PhpCreateGetters() 72 | nnoremap da :call PhpDocAll() 73 | endif 74 | " }}} 75 | 76 | " +--------------------------------------------------------------+ 77 | " | VIM REGEXP REMINDER | Vim Regex | Perl Regex | 78 | " |===============================================================| 79 | " | Vim non catchable | \%(.\) | (?:.) | 80 | " | Vim negative lookahead | Start\(Date\)\@! | Start(?!Date) | 81 | " | Vim positive lookahead | Start\(Date\)\@= | Start(?=Date) | 82 | " | Vim negative lookbehind | \(Start\)\@\|trait\>\)' 92 | let s:php_regex_const_line = '^\s*const\s\+[^;]\+;' 93 | let s:php_regex_member_line = '^\s*\%(\%(private\|protected\|public\|static\)\%(\_s\+?\?[\\|_A-Za-z0-9]\+\)\?\s*\)\+\$' 94 | let s:php_regex_func_line = '^\s*\%(\%(private\|protected\|public\|static\|abstract\)\s*\)*function\_s\+' 95 | 96 | let s:php_regex_local_var = '\$\<\%(this\>\)\@![A-Za-z0-9]*' 97 | let s:php_regex_assignment = '+=\|-=\|*=\|/=\|=\~\|!=\|=' 98 | let s:php_regex_fqcn = '[\\_A-Za-z0-9]*' 99 | let s:php_regex_cn = '[_A-Za-z0-9]\+' 100 | " }}} 101 | 102 | " Fluent {{{ 103 | let s:php_fluent_this = "normal! jo\return $this;" 104 | " }}} 105 | 106 | function! PhpDocAll() " {{{ 107 | if exists("*" . g:vim_php_refactoring_phpdoc) == 0 108 | call s:PhpEchoError(g:vim_php_refactoring_phpdoc . '() vim function doesn''t exists.') 109 | return 110 | endif 111 | normal! magg 112 | while search(s:php_regex_class_line, 'eW') > 0 113 | call s:PhpDocument() 114 | endwhile 115 | normal! gg 116 | while search(s:php_regex_member_line, 'eW') > 0 117 | call s:PhpDocument() 118 | endwhile 119 | normal! gg 120 | while search(s:php_regex_func_line, 'eW') > 0 121 | call s:PhpDocument() 122 | endwhile 123 | normal! `a 124 | endfunction 125 | " }}} 126 | 127 | function! PhpCreateGetters() " {{{ 128 | normal! gg 129 | let l:properties = [] 130 | while search(s:php_regex_member_line, 'eW') > 0 131 | normal! w"xye 132 | call add(l:properties, @x) 133 | endwhile 134 | for l:property in l:properties 135 | let l:camelCaseName = substitute(l:property, '^_\?\(.\)', '\U\1', '') 136 | if g:vim_php_refactoring_auto_validate_g == 0 137 | call s:PhpEchoError('Create get' . l:camelCaseName . '()') 138 | if inputlist(["0. No", "1. Yes"]) == 0 139 | continue 140 | endif 141 | endif 142 | if search(s:php_regex_func_line . "get" . l:camelCaseName . '\>', 'n') == 0 143 | call s:PhpInsertMethod("public", "get" . l:camelCaseName, [], "return $this->" . l:property . ";\n") 144 | endif 145 | endfor 146 | endfunction 147 | " }}} 148 | 149 | function! PhpCreateSettersAndGetters() " {{{ 150 | normal! gg 151 | let l:properties = [] 152 | while search(s:php_regex_member_line, 'eW') > 0 153 | normal! w"xye 154 | call add(l:properties, @x) 155 | endwhile 156 | for l:property in l:properties 157 | let l:camelCaseName = substitute(l:property, '^_\?\(.\)', '\U\1', '') 158 | if g:vim_php_refactoring_auto_validate_sg == 0 159 | call s:PhpEchoError('Create set' . l:camelCaseName . '() and get' . l:camelCaseName . '()') 160 | if inputlist(["0. No", "1. Yes"]) == 0 161 | continue 162 | endif 163 | endif 164 | if search(s:php_regex_func_line . "set" . l:camelCaseName . '\>', 'n') == 0 165 | call s:PhpInsertMethod("public", "set" . l:camelCaseName, ['$' . substitute(l:property, '^_', '', '') ], "$this->" . l:property . " = $" . substitute(l:property, '^_', '', '') . ";\n") 166 | if g:vim_php_refactoring_make_setter_fluent > 0 167 | call s:PhpInsertFluent() 168 | endif 169 | endif 170 | if search(s:php_regex_func_line . "get" . l:camelCaseName . '\>', 'n') == 0 171 | call s:PhpInsertMethod("public", "get" . l:camelCaseName, [], "return $this->" . l:property . ";\n") 172 | endif 173 | endfor 174 | endfunction 175 | " }}} 176 | 177 | function! PhpRenameLocalVariable() " {{{ 178 | let l:oldName = substitute(expand(''), '^\$*', '', '') 179 | let l:newName = inputdialog('Rename ' . l:oldName . ' to: ') 180 | if g:vim_php_refactoring_auto_validate_rename == 0 181 | if s:PhpSearchInCurrentFunction('\C$' . l:newName . '\>', 'n') > 0 182 | call s:PhpEchoError('$' . l:newName . ' seems to already exist in the current function scope. Rename anyway ?') 183 | if inputlist(["0. No", "1. Yes"]) == 0 184 | return 185 | endif 186 | endif 187 | endif 188 | call s:PhpReplaceInCurrentFunction('\C$' . l:oldName . '\>', '$' . l:newName) 189 | endfunction 190 | " }}} 191 | 192 | function! PhpRenameClassVariable() " {{{ 193 | let l:oldName = substitute(expand(''), '^\$*', '', '') 194 | let l:newName = inputdialog('Rename ' . l:oldName . ' to: ') 195 | if g:vim_php_refactoring_auto_validate_rename == 0 196 | if s:PhpSearchInCurrentClass('\C\%(\%(\%(public\|protected\|private\|static\)\%(\_s\+?\?[\\|_A-Za-z0-9]\+\)\?\_s\+\)\+\$\|$this->\)\@<=' . l:newName . '\>', 'n') > 0 197 | call s:PhpEchoError(l:newName . ' seems to already exist in the current class. Rename anyway ?') 198 | if inputlist(["0. No", "1. Yes"]) == 0 199 | return 200 | endif 201 | endif 202 | endif 203 | call s:PhpReplaceInCurrentClass('\C\%(\%(\%(public\|protected\|private\|static\)\%(\_s\+?\?[\\|_A-Za-z0-9]\+\)\?\_s\+\)\+\$\|$this->\)\@<=' . l:oldName . '\>', l:newName) 204 | endfunction 205 | " }}} 206 | 207 | function! PhpRenameMethod() " {{{ 208 | let l:oldName = substitute(expand(''), '^\$*', '', '') 209 | let l:newName = inputdialog('Rename ' . l:oldName . ' to: ') 210 | if g:vim_php_refactoring_auto_validate_rename == 0 211 | if s:PhpSearchInCurrentClass('\%(\%(' . s:php_regex_func_line . '\)\|$this->\)\@<=' . l:newName . '\>', 'n') > 0 212 | call s:PhpEchoError(l:newName . ' seems to already exist in the current class. Rename anyway ?') 213 | if inputlist(["0. No", "1. Yes"]) == 0 214 | return 215 | endif 216 | endif 217 | endif 218 | call s:PhpReplaceInCurrentClass('\%(\%(' . s:php_regex_func_line . '\)\|$this->\)\@<=' . l:oldName . '\>', l:newName) 219 | endfunction 220 | " }}} 221 | 222 | function! PhpExtractUse() " {{{ 223 | normal! mr 224 | let l:fqcn = s:PhpGetFQCNUnderCursor() 225 | let l:use = s:PhpGetDefaultUse(l:fqcn) 226 | let l:defaultUse = l:use 227 | if strlen(use) == 0 228 | let defaultUse = s:PhpGetShortClassName(l:fqcn) 229 | endif 230 | 231 | " Use negative lookahead and behind to make sure we don't replace exact string 232 | exec ':%s/\%([''"]\)\@'), '^\$*', '', '') 258 | call s:PhpReplaceInCurrentFunction('$' . l:name . '\>', '$this->' . l:name) 259 | if g:vim_php_refactoring_auto_validate_visibility == 0 260 | let l:visibility = inputdialog("Visibility (default is " . g:vim_php_refactoring_default_property_visibility . "): ") 261 | if empty(l:visibility) 262 | let l:visibility = g:vim_php_refactoring_default_property_visibility 263 | endif 264 | else 265 | let l:visibility = g:vim_php_refactoring_default_property_visibility 266 | endif 267 | call s:PhpInsertProperty(l:name, l:visibility) 268 | normal! `r 269 | endfunction 270 | " }}} 271 | 272 | function! PhpExtractMethod() range " {{{ 273 | if visualmode() == '' 274 | call s:PhpEchoError('Extract method doesn''t works in Visual Block mode. Use Visual line or Visual mode.') 275 | return 276 | endif 277 | let l:name = inputdialog("Name of new method: ") 278 | if g:vim_php_refactoring_auto_validate_visibility == 0 279 | let l:visibility = inputdialog("Visibility (default is " . g:vim_php_refactoring_default_method_visibility . "): ") 280 | if empty(l:visibility) 281 | let l:visibility = g:vim_php_refactoring_default_method_visibility 282 | endif 283 | else 284 | let l:visibility = g:vim_php_refactoring_default_method_visibility 285 | endif 286 | normal! gv"xdmr 287 | let l:middleLine = line('.') 288 | call search(s:php_regex_func_line, 'bW') 289 | let l:startLine = line('.') 290 | call search('(', 'W') 291 | normal! "pyi( 292 | call search('{', 'W') 293 | exec "normal! %" 294 | let l:stopLine = line('.') 295 | let l:beforeExtract = join(getline(l:startLine, l:middleLine-1)) 296 | let l:afterExtract = join(getline(l:middleLine, l:stopLine)) 297 | let l:parameters = [] 298 | let l:parametersSignature = [] 299 | let l:output = [] 300 | for l:var in s:PhpMatchAllStr(@x, s:php_regex_local_var) 301 | if match(l:beforeExtract, l:var . '\>') > 0 302 | call add(l:parameters, l:var) 303 | if @p =~ '[^,]*' . l:var . '\>[^,]*' 304 | call add(l:parametersSignature, substitute(matchstr(@p, '[^,]*' . l:var . '\>[^,]*'), '^\s*\(.\{-}\)\s*$', '\1', 'g')) 305 | else 306 | call add(l:parametersSignature, l:var) 307 | endif 308 | endif 309 | if match(l:afterExtract, l:var . '\>') > 0 310 | call add(l:output, l:var) 311 | endif 312 | endfor 313 | normal! `r 314 | if len(l:output) == 0 315 | exec "normal! O$this->" . l:name . "(" . join(l:parameters, ", ") . ");\k=3=" 316 | let l:return = '' 317 | elseif len(l:output) == 1 318 | exec "normal! O" . l:output[0] . " = $this->" . l:name . "(" . join(l:parameters, ", ") . ");\=3=" 319 | let l:return = "return " . l:output[0] . ";\" 320 | else 321 | exec "normal! Olist(" . join(l:output, ", ") . ") = $this->" . l:name . "(" . join(l:parameters, ", ") . ");\=3=" 322 | let l:return = "return array(" . join(l:output, ", ") . ");\" 323 | endif 324 | call s:PhpInsertMethod(l:visibility, l:name, l:parametersSignature, @x . l:return) 325 | normal! `r 326 | endfunction 327 | " }}} 328 | 329 | function! PhpCreateProperty() " {{{ 330 | let l:name = inputdialog("Name of new property: ") 331 | if g:vim_php_refactoring_auto_validate_visibility == 0 332 | let l:visibility = inputdialog("Visibility (default is " . g:vim_php_refactoring_default_property_visibility . "): ") 333 | if empty(l:visibility) 334 | let l:visibility = g:vim_php_refactoring_default_property_visibility 335 | endif 336 | else 337 | let l:visibility = g:vim_php_refactoring_default_property_visibility 338 | endif 339 | call s:PhpInsertProperty(l:name, l:visibility) 340 | endfunction 341 | " }}} 342 | 343 | function! PhpDetectUnusedUseStatements() " {{{ 344 | normal! mrgg 345 | while search('^use', 'W') 346 | let l:startLine = line('.') 347 | call search(';\_s*', 'eW') 348 | let l:endLine = line('.') 349 | let l:line = join(getline(l:startLine, l:endLine)) 350 | for l:useStatement in split(substitute(l:line, '^\%(use\)\?\s*\([^;]*\);', '\1', ''), ',') 351 | let l:matches = matchlist(l:useStatement, '\s*\\\?\%([_A-Za-z0-9]\+\\\)*\([_A-Za-z0-9]\+\)\%(\s*as\s*\([_A-Za-z0-9]\+\)\)\?') 352 | let l:alias = s:PhpPopList(l:matches) 353 | if search(l:alias, 'nW') == 0 354 | echo 'Unused: ' . l:useStatement 355 | endif 356 | endfor 357 | endwhile 358 | normal! `r 359 | endfunction 360 | " }}} 361 | 362 | function! PhpAlignAssigns() range " {{{ 363 | " This funcion was took from : 364 | " Vim refactoring plugin 365 | " Maintainer: Eustaquio 'TaQ' Rangel 366 | " License: GPL 367 | " URL: git://github.com/taq/vim-refact.git 368 | let l:max = 0 369 | let l:maxo = 0 370 | let l:linc = "" 371 | for l:line in range(a:firstline,a:lastline) 372 | let l:linc = getbufline("%", l:line)[0] 373 | let l:rst = match(l:linc, '\%(' . s:php_regex_assignment . '\)') 374 | if l:rst < 0 375 | continue 376 | endif 377 | let l:rstl = matchstr(l:linc, '\%(' . s:php_regex_assignment . '\)') 378 | let l:max = max([l:max, strlen(substitute(strpart(l:linc, 0, l:rst), '\s*$', '', '')) + 1]) 379 | let l:maxo = max([l:maxo, strlen(l:rstl)]) 380 | endfor 381 | let l:formatter= '\=printf("%-'.l:max.'s%-'.l:maxo.'s%s",submatch(1),submatch(2),submatch(3))' 382 | let l:expr = '^\(.\{-}\)\s*\('.s:php_regex_assignment.'\)\(.*\)' 383 | for l:line in range(a:firstline,a:lastline) 384 | let l:oldline = getbufline("%",l:line)[0] 385 | let l:newline = substitute(l:oldline,l:expr,l:formatter,"") 386 | call setline(l:line,l:newline) 387 | endfor 388 | endfunction 389 | " }}} 390 | 391 | function! s:PhpDocument() " {{{ 392 | if match(getline(line('.')-1), "*/") == -1 393 | normal! mr 394 | exec "call " . g:vim_php_refactoring_phpdoc . '()' 395 | normal! `r 396 | endif 397 | endfunction 398 | " }}} 399 | 400 | function! s:PhpReplaceInCurrentFunction(search, replace) " {{{ 401 | normal! mr 402 | call search(s:php_regex_func_line, 'bW') 403 | let l:startLine = line('.') 404 | call search('{', 'W') 405 | exec "normal! %" 406 | let l:stopLine = line('.') 407 | exec l:startLine . ',' . l:stopLine . ':s/' . a:search . '/'. a:replace .'/ge' 408 | normal! `r 409 | endfunction 410 | " }}} 411 | 412 | function! s:PhpReplaceInCurrentClass(search, replace) " {{{ 413 | normal! mr 414 | call search(s:php_regex_class_line, 'beW') 415 | call search('{', 'W') 416 | let l:startLine = line('.') 417 | exec "normal! %" 418 | let l:stopLine = line('.') 419 | exec l:startLine . ',' . l:stopLine . ':s/' . a:search . '/'. a:replace .'/ge' 420 | normal! `r 421 | endfunction 422 | " }}} 423 | 424 | function! s:PhpInsertUseStatement(use) " {{{ 425 | let l:use = 'use ' . substitute(a:use, '^\\', '', '') . ';' 426 | if search(s:php_regex_use_line, 'beW') > 0 427 | call append(line('.'), l:use) 428 | elseif search(s:php_regex_ns_line, 'beW') > 0 429 | call append(line('.'), '') 430 | call append(line('.')+1, l:use) 431 | elseif search(s:php_regex_phptag_line, 'beW') > 0 432 | call append(line('.'), '') 433 | call append(line('.')+1, l:use) 434 | else 435 | call append(1, l:use) 436 | endif 437 | endfunction 438 | " }}} 439 | 440 | function! s:PhpInsertConst(name, value) " {{{ 441 | if search(s:php_regex_const_line, 'beW') > 0 442 | call append(line('.'), 'const ' . a:name . ' = ' . a:value . ';') 443 | elseif search(s:php_regex_class_line, 'beW') > 0 444 | call search('{', 'W') 445 | call append(line('.'), 'const ' . a:name . ' = ' . a:value . ';') 446 | call append(line('.')+1, '') 447 | else 448 | call append(line('.'), 'const ' . a:name . ' = ' . a:value . ';') 449 | endif 450 | normal! j=1= 451 | endfunction 452 | " }}} 453 | 454 | function! s:PhpInsertProperty(name, visibility) " {{{ 455 | let l:regex = '\%(' . join([s:php_regex_member_line, s:php_regex_const_line, s:php_regex_class_line], '\)\|\(') .'\)' 456 | if search(l:regex, 'beW') > 0 457 | let l:line = getbufline("%", line('.'))[0] 458 | if match(l:line, s:php_regex_class_line) > -1 459 | call search('{', 'W') 460 | call s:PhpInsertPropertyExtended(a:name, a:visibility, line('.'), 0) 461 | else 462 | call search(';', 'W') 463 | call s:PhpInsertPropertyExtended(a:name, a:visibility, line('.'), 1) 464 | endif 465 | else 466 | call search(';', 'W') 467 | call s:PhpInsertPropertyExtended(a:name, a:visibility, line('.'), 0) 468 | endif 469 | endfunction 470 | " }}} 471 | 472 | function! s:PhpInsertPropertyExtended(name, visibility, insertLine, emptyLineBefore) " {{{ 473 | call append(a:insertLine, '') 474 | call append(a:insertLine + a:emptyLineBefore, '/**') 475 | call append(a:insertLine + a:emptyLineBefore + 1, '* @var mixed') 476 | call append(a:insertLine + a:emptyLineBefore + 2, '*/') 477 | call append(a:insertLine + a:emptyLineBefore + 3, a:visibility . " $" . a:name . ';') 478 | normal! j=5= 479 | endfunction 480 | " }}} 481 | 482 | function! s:PhpInsertMethod(modifiers, name, params, impl) " {{{ 483 | call search(s:php_regex_func_line, 'beW') 484 | call search('{', 'W') 485 | exec "normal! %" 486 | exec "normal! o\" . a:modifiers . " function " . a:name . "(" . join(a:params, ", ") . ")\{\" . a:impl . "}\=a{" 487 | endfunction 488 | " }}} 489 | 490 | function! s:PhpGetFQCNUnderCursor() " {{{ 491 | let l:line = getbufline("%", line('.'))[0] 492 | let l:lineStart = strpart(l:line, 0, col('.')) 493 | let l:lineEnd = strpart(l:line, col('.'), strlen(l:line) - col('.')) 494 | return matchstr(l:lineStart, s:php_regex_fqcn . '$') . matchstr(l:lineEnd, '^' . s:php_regex_cn) 495 | endfunction 496 | " }}} 497 | 498 | function! s:PhpGetShortClassName(fqcn) " {{{ 499 | return matchstr(a:fqcn, s:php_regex_cn . '$') 500 | endfunction 501 | " }}} 502 | 503 | function! s:PhpGetDefaultUse(fqcn) " {{{ 504 | return inputdialog("Use as [Default: " . s:PhpGetShortClassName(a:fqcn) ."] : ") 505 | endfunction 506 | " }}} 507 | 508 | function! s:PhpPopList(list) " {{{ 509 | for l:elem in reverse(a:list) 510 | if strlen(l:elem) > 0 511 | return l:elem 512 | endif 513 | endfor 514 | endfunction 515 | " }}} 516 | 517 | function! s:PhpSearchInCurrentFunction(pattern, flags) " {{{ 518 | normal! mr 519 | call search(s:php_regex_func_line, 'bW') 520 | let l:startLine = line('.') 521 | call search('{', 'W') 522 | exec "normal! %" 523 | let l:stopLine = line('.') 524 | normal! `r 525 | return s:PhpSearchInRange(a:pattern, a:flags, l:startLine, l:stopLine) 526 | endfunction 527 | " }}} 528 | 529 | function! s:PhpSearchInCurrentClass(pattern, flags) " {{{ 530 | normal! mr 531 | call search(s:php_regex_class_line, 'beW') 532 | call search('{', 'W') 533 | let l:startLine = line('.') 534 | exec "normal! %" 535 | let l:stopLine = line('.') 536 | normal! `r 537 | return s:PhpSearchInRange(a:pattern, a:flags, l:startLine, l:stopLine) 538 | endfunction 539 | " }}} 540 | 541 | function! s:PhpSearchInRange(pattern, flags, startLine, endLine) " {{{ 542 | return search('\%>' . a:startLine . 'l\%<' . a:endLine . 'l' . a:pattern, a:flags) 543 | endfunction 544 | " }}} 545 | 546 | function! s:PhpMatchAllStr(haystack, needle) " {{{ 547 | let l:result = [] 548 | let l:matchPos = match(a:haystack, a:needle, 0) 549 | while l:matchPos > 0 550 | let l:str = matchstr(a:haystack, a:needle, l:matchPos) 551 | if index(l:result, l:str) < 0 552 | call add(l:result, l:str) 553 | endif 554 | let l:matchPos = match(a:haystack, a:needle, l:matchPos + strlen(l:str)) 555 | endwhile 556 | return l:result 557 | endfunction 558 | " }}} 559 | 560 | function! s:PhpEchoError(message) " {{{ 561 | echohl ErrorMsg 562 | echomsg a:message 563 | echohl NONE 564 | endfunction 565 | " }}} 566 | 567 | function! s:PhpInsertFluent() " {{{ 568 | if g:vim_php_refactoring_make_setter_fluent == 1 569 | exec s:php_fluent_this 570 | elseif g:vim_php_refactoring_make_setter_fluent == 2 571 | call s:PhpEchoError('Make fluent?') 572 | if inputlist(["0. No", "1. Yes"]) == 1 573 | exec s:php_fluent_this 574 | endif 575 | else 576 | echoerr 'Invalid option for g:vim_php_refactoring_make_setter_fluent' 577 | endif 578 | endfunction 579 | " }}} 580 | --------------------------------------------------------------------------------