Changes On Branch refactoring-tool-script Вы: nobody
Вход

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch refactoring-tool-script Excluding Merge-Ins

This is equivalent to a diff from 005eb1cbc0 to 7b85160c52

2012-06-27
08:48
поправлена группировка слова "function" check-in: e704b0c444 user: metaeditor tags: trunk
2012-06-25
04:16
Скрипт для выполнения рефакторинга кода 1С по просьбам перенесен в основную ветку. check-in: 8c40cf72ad user: kuntashov tags: trunk
04:13
Убрал вызов отладчика. Leaf check-in: 7b85160c52 user: kuntashov tags: refactoring-tool-script
04:04
Синхронизировано с trunk. check-in: 708535a257 user: kuntashov tags: refactoring-tool-script
2012-06-24
13:32
SciColorerV8\SciColorerV8.dll check-in: 005eb1cbc0 user: metaeditor tags: trunk
12:29
SciColorerV8\SciColorerV8.dll check-in: b4608296fa user: metaeditor tags: trunk

Changes to Libs/SyntaxAnalysis.js.

   267    267       var method = this.context.getMethodByName(methodName);
   268    268       if (!method) return undefined;
   269    269       return this.textWindow.Range(method.StartLine + 1, 1, method.EndLine + 1).GetText();
   270    270   }
   271    271   
   272    272   /* Возвращает таблицу значений с описаниями методов модуля. */
   273    273   _1CModule.prototype.getMethodsTable = function() {
   274         -    return this.context._vtAllMethods;
          274  +    return this.context._vtAllMethods.Copy();
   275    275   }
   276    276   
   277    277   /* Возвращает описание метода по номеру строки, находящейся внутри метода. */
   278    278   _1CModule.prototype.getMethodByLineNumber = function (lineNo) {
   279    279   
   280    280       var methods = this.context.Methods;
   281    281       

Changes to Tests/Automated/SyntaxAnalysis/testSyntaxAnalysis.js.

    13     13   }
    14     14   
    15     15   function tearDown() {
    16     16   }
    17     17   //} setUp/tearDown
    18     18   
    19     19   //{ tests of AnalyseModule
    20         -
    21     20   function macrosTestAnalyseModule1() {
    22     21   
    23     22       var moduleText = ""
    24     23           + "Перем мПеременнаяМодуля;\n\n"
    25     24           + "Перем ЕщеОднаПеременная;\n"
    26     25           + "Перем ЭкспортнаяПеременная Экспорт;\n"
    27     26           + "Перем ЭкспортныйМассив[10] Экспорт, ЛокальныйМассив[3], ПростоПеременная;\n"
................................................................................
   249    248   
   250    249       var cnt = SyntaxAnalysis.AnalyseModule(moduleText);
   251    250   
   252    251       assertEquals('Неправильно определено количество методов!', 1, cnt.Methods.length);    
   253    252       assertEquals('Неправильно определено количество переменных модуля!', 0, cnt.ModuleVars.length);
   254    253   }
   255    254   
   256         -function macrosTestAnalyseModule10_ОпределениеПараметровМетодаНаРазныхСтроках() {
          255  +function macrosTestAnalyseModule10_ОпределениеМетодаНаРазныхСтроках2() {
          256  +    var moduleText = ""
          257  +        + "Процедура Проверки ( Перем1, \n"
          258  +        + "    Перем2, Перем3)\n"
          259  +        + "КонецПроцедуры"
          260  +    
          261  +    var cnt = SyntaxAnalysis.AnalyseModule(moduleText);
          262  +
          263  +    assertEquals('Неправильно определено количество методов!', 1, cnt.Methods.length);    
          264  +    assertEquals('Неправильно определено количество переменных модуля!', 0, cnt.ModuleVars.length);
          265  +}
          266  +
          267  +function macrosTestAnalyseModule11_ОпределениеПараметровМетодаНаРазныхСтроках() {
   257    268       var moduleText = ""
   258    269           + "Процедура Проверки ( Перем1, \n"
   259    270           + "    Перем2, Перем3)\n"
   260    271           + "КонецПроцедуры"
   261    272       //debugger
   262    273       var cnt = SyntaxAnalysis.AnalyseModule(moduleText);
   263    274   
................................................................................
   264    275       assertEquals('Неправильно определено количество методов!', 1, cnt.Methods.length);    
   265    276       assertEquals('Неправильно определено количество переменных модуля!', 0, cnt.ModuleVars.length);
   266    277       var proc = cnt.getMethodByName('Проверки');
   267    278       assertNotNull("Метод Проверки не найден", proc);    
   268    279       assertArrayEqualsIgnoringOrder(['Перем1', 'Перем2', 'Перем3'], proc.Params);
   269    280   }
   270    281   
   271         -function macrosTestAnalyseModule11_ОпределениеПеременныхМетодаПоУмолчанию() {
          282  +function macrosTestAnalyseModule12_ОпределениеПеременныхМетодаПоУмолчанию() {
   272    283       var moduleText = ""
   273    284           + "Процедура Проверки (Знач Парам1, Парам2 = Ложь)\n"
   274    285           + "КонецПроцедуры"
   275    286       //debugger
   276    287       var cnt = SyntaxAnalysis.AnalyseModule(moduleText);
   277    288   
   278    289       assertEquals('Неправильно определено количество методов!', 1, cnt.Methods.length);    
................................................................................
   279    290       assertEquals('Неправильно определено количество переменных модуля!', 0, cnt.ModuleVars.length);
   280    291       var proc = cnt.getMethodByName('Проверки');
   281    292       assertNotNull("Метод Проверки не найден", proc);    
   282    293       assertArrayEqualsIgnoringOrder(['Парам1', 'Парам2'], proc.Params);
   283    294       
   284    295   }
   285    296   
   286         -function macrosTestAnalyseModule12_ОпределениеКонеткстаКомпиляции() {
          297  +function macrosTestAnalyseModule13_ОпределениеКонеткстаКомпиляции() {
   287    298       var moduleText = ""
   288    299           + "&НаКлиенте\n"
   289    300           + "Процедура Проверки (Знач Парам1, Парам2 = Ложь)\n"
   290    301           + "КонецПроцедуры"
   291    302       var cnt = SyntaxAnalysis.AnalyseModule(moduleText);
   292    303   
   293    304       assertEquals('Неправильно определено количество методов!', 1, cnt.Methods.length);    
................................................................................
   294    305       assertEquals('Неправильно определено количество переменных модуля!', 0, cnt.ModuleVars.length);
   295    306       var proc = cnt.getMethodByName('Проверки');
   296    307       assertNotNull("Метод Проверки не найден", proc);    
   297    308       assertEquals("Конетекст компиляции не обнаружен", "НаКлиенте", proc.Context)
   298    309       assertArrayEqualsIgnoringOrder(['Парам1', 'Парам2'], proc.Params);
   299    310       
   300    311   }
   301         -function macrosTestAnalyseModule13_ОпределениеПараметровМетодаНаРазныхСтрокахСКомментариями() {
          312  +function macrosTestAnalyseModule14_ОпределениеПараметровМетодаНаРазныхСтрокахСКомментариями() {
   302    313       var moduleText = ""
   303    314           + "Процедура Проверки ( Перем1, //Текстовый комментарий перемменной, да и такое может быть.  \n"
   304    315           + "    Перем2, Перем3)\n"
   305    316           + "КонецПроцедуры"
   306    317       debugger
   307    318       var cnt = SyntaxAnalysis.AnalyseModule(moduleText);
   308    319   
................................................................................
   309    320       assertEquals('Неправильно определено количество методов!', 1, cnt.Methods.length);    
   310    321       assertEquals('Неправильно определено количество переменных модуля!', 0, cnt.ModuleVars.length);
   311    322       var proc = cnt.getMethodByName('Проверки');
   312    323       assertNotNull("Метод Проверки не найден", proc);    
   313    324       assertArrayEqualsIgnoringOrder(['Перем1', 'Перем2', 'Перем3'], proc.Params);
   314    325   }
   315    326   
   316         -function macrosTestAnalyseModule14_ОпределениеПараметровМетодаНаРазныхСтрокахСКомментариямиИСкобками() {
          327  +function macrosTestAnalyseModule15_ОпределениеПараметровМетодаНаРазныхСтрокахСКомментариямиИСкобками() {
   317    328       var moduleText = ""
   318    329           + "Процедура Проверки ( Перем1, //Текстовый комментарий перемменной, да и такое может быть.  \n"
   319    330           + "    Перем2, // Любой текст и ссылка на процедуру или функцию МояПроцедура()\n"
   320    331           + "    Перем3)\n"
   321    332           + "КонецПроцедуры"
   322    333       
   323    334       var cnt = SyntaxAnalysis.AnalyseModule(moduleText);
................................................................................
   324    335   
   325    336       assertEquals('Неправильно определено количество методов!', 1, cnt.Methods.length);    
   326    337       assertEquals('Неправильно определено количество переменных модуля!', 0, cnt.ModuleVars.length);
   327    338       var proc = cnt.getMethodByName('Проверки');
   328    339       assertNotNull("Метод Проверки не найден", proc);    
   329    340       assertArrayEqualsIgnoringOrder(['Перем1', 'Перем2', 'Перем3'], proc.Params);
   330    341   }
   331         -
   332    342   
   333    343   
   334    344   //} tests of AnalyseModule
   335    345   

Added refactoring.extractMethod.ssf.

cannot compute difference between binary files

Added refactoring.js.

            1  +$engine JScript
            2  +$uname Refactoring
            3  +$dname Рефакторинг
            4  +$addin global
            5  +$addin stdlib
            6  +$addin vbs
            7  +
            8  +////////////////////////////////////////////////////////////////////////////////////////
            9  +////{ Cкрипт "Рефакторинг" (refactoring.js) для проекта "Снегопат"
           10  +////
           11  +//// Описание: Реализует простейшие инструменты рефакторинга.
           12  +//// Автор: Александр Кунташов <kuntashov@gmail.com>, http://compaud.ru/blog
           13  +////}
           14  +////////////////////////////////////////////////////////////////////////////////////////
           15  +
           16  +stdlib.require('TextWindow.js', SelfScript);
           17  +stdlib.require('SettingsManagement.js', SelfScript);
           18  +
           19  +stdlib.require('SyntaxAnalysis.js', SelfScript);
           20  +//Для отладки: stdlib.require(profileRoot.getValue("Snegopat/MainFolder") + 'user\\Libs\\SyntaxAnalysis.js', SelfScript); 
           21  +
           22  +global.connectGlobals(SelfScript);
           23  +
           24  +////////////////////////////////////////////////////////////////////////////////////////
           25  +////{ Макросы
           26  +////
           27  +
           28  +SelfScript.self['macrosВыделить метод (extract method)'] = function () {
           29  +    refactor(ExtractMethodRefactoring);
           30  +}
           31  +
           32  +SelfScript.self['macrosПоказать список процедур и функций модуля'] = function () {
           33  +    var tw = GetTextWindow();
           34  +    if (!tw) return;
           35  +    var module = SyntaxAnalysis.AnalyseTextDocument(tw);
           36  +    var methList = new MethodListForm(module);
           37  +    if (methList.selectMethod())
           38  +        Message(methList.SelectedMethod.Name);
           39  +}
           40  +
           41  +SelfScript.self['macrosСоздать заглушку для несуществующего метода'] = function () {
           42  +    refactor(CreateMethodStubRefactoring, true);
           43  +}
           44  +
           45  +////} Макросы
           46  +
           47  +function refactor(refactorerClass, withoutSelection) {
           48  +    
           49  +    var tw = GetTextWindow();
           50  +    if (!tw) return;
           51  +    
           52  +    var selText = tw.GetSelectedText();
           53  +    if (!selText && !withoutSelection) 
           54  +    {
           55  +        Message("Не выделен текст, к которому применяется рефакторинг!");
           56  +        return;
           57  +    }
           58  +    
           59  +    var module = SyntaxAnalysis.AnalyseTextDocument(tw);
           60  +    var refactorer = new refactorerClass(module);
           61  +    refactorer.refactor(selText);
           62  +}
           63  +
           64  +////////////////////////////////////////////////////////////////////////////////////////
           65  +////{ MethodListForm
           66  +////
           67  +
           68  +function MethodListForm(module) {
           69  +
           70  +    this.module = module;
           71  +    this.originalMethodList = module.getMethodsTable();
           72  +
           73  +    this.form = loadScriptForm(SelfScript.fullPath.replace(/\.js$/, '.methodList.ssf'), this);
           74  +    this.SelectedMethod = undefined;
           75  +    
           76  +    this.settings = SettingsManagement.CreateManager(SelfScript.uniqueName + "/MethodListForm", {
           77  +        'DoNotFilter': false, 'SortByName' : false
           78  +    });
           79  +    
           80  +    this.settings.LoadSettings();
           81  +        
           82  +    var methListForm = this;
           83  +    this.tcWatcher = new TextChangesWatcher(this.form.Controls.SearchText, 3, function(t){methListForm.fillMethodList(t)});
           84  +    
           85  +    this.icons = {
           86  +        'Proc': this.form.Controls.picProc.Picture,
           87  +        'Func': this.form.Controls.picFunc.Picture
           88  +    }
           89  +    
           90  +    this.fillMethodList();
           91  +}
           92  +
           93  +MethodListForm.prototype.selectMethod = function () {
           94  +    this.SelectedMethod = this.form.DoModal();
           95  +    return this.SelectedMethod ? true : false;
           96  +}
           97  +
           98  +MethodListForm.prototype.MethodListSelection = function (Control, SelectedRow, Column, DefaultHandler) {
           99  +    this.form.Close(SelectedRow.val._method);
          100  +}
          101  +
          102  +MethodListForm.prototype.MethodListOnRowOutput = function (Control, RowAppearance, RowData) {
          103  +    var nameCell = RowAppearance.val.Cells.Name;
          104  +    nameCell.SetPicture( RowData.val.IsProc ? this.icons.Proc : this.icons.Func);
          105  +}
          106  +
          107  +MethodListForm.prototype.CmdBarSortByName = function (button) {
          108  +    button.val.Check = !button.val.Check;
          109  +    this.form.SortByName = button.val.Check;
          110  +    this.sortMethodList(button.val.Check);
          111  +}
          112  +
          113  +MethodListForm.prototype.CmdBarDoNotFilter = function (button) {
          114  +    button.val.Check = !button.val.Check;
          115  +    this.form.DoNotFilter = button.val.Check;
          116  +    this.fillMethodList(this.form.SearchText);
          117  +}
          118  +
          119  +MethodListForm.prototype.CmdBarMainОК = function (Кнопка) {
          120  +    var SelectedRow = this.form.Controls.MethodList.CurrentRow;
          121  +    if (SelectedRow)
          122  +        this.form.Close(SelectedRow._method);
          123  +    else
          124  +        this.form.CurrentControl = this.form.Controls.SearchText;
          125  +}
          126  +
          127  +MethodListForm.prototype.OnOpen = function () {
          128  +
          129  +    this.settings.ApplyToForm(this.form);
          130  +
          131  +    this.form.Controls.CmdBar.Buttons.SortByName.Check = this.form.SortByName;
          132  +    this.form.Controls.CmdBar.Buttons.DoNotFilter.Check = this.form.DoNotFilter;
          133  +    
          134  +    this.loadedOnOpen = true;
          135  +    this.tcWatcher.start();
          136  +}
          137  +
          138  +MethodListForm.prototype.BeforeClose = function (Cancel, StandardHandler) {
          139  +    this.tcWatcher.stop();
          140  +    this.saveSettings();
          141  +}
          142  +
          143  +MethodListForm.prototype.fillMethodList = function (newText) {
          144  +
          145  +    if (!newText || newText.match(/^\s*$/))
          146  +    {
          147  +        if (this.loadedOnOpen)
          148  +            this.loadedOnOpen = false;
          149  +        else
          150  +            this.form.Controls.MethodList.Value = this.originalMethodList.Copy();            
          151  +    }
          152  +    else 
          153  +    {
          154  +        var a = newText.split(/\s+/);
          155  +        for (var i=0; i<a.length; i++)
          156  +            a[i] = StringUtils.addSlashes(a[i]);
          157  +            
          158  +        var re = new RegExp(a.join(".*?"), 'i');    
          159  +        
          160  +        if (this.form.DoNotFilter)
          161  +        {
          162  +            var currentRow = undefined;
          163  +            
          164  +            var methList = this.originalMethodList.Copy();
          165  +            for (var rowNo = 0; rowNo < methList.Count(); rowNo++)
          166  +            {
          167  +                var row = methList.Get(rowNo);
          168  +                if (re.test(row.Name))
          169  +                {
          170  +                    currentRow = row;
          171  +                    break;
          172  +                }
          173  +            }
          174  +            
          175  +            this.form.Controls.MethodList.Value = methList;
          176  +            if (currentRow)
          177  +                this.form.Controls.MethodList.CurrentRow = currentRow;
          178  +        }
          179  +        else
          180  +        {
          181  +            var methList = this.form.Controls.MethodList.Value;
          182  +            methList.Clear();    
          183  +            for (var rowNo = 0; rowNo < this.originalMethodList.Count(); rowNo++)
          184  +            {
          185  +                var row = this.originalMethodList.Get(rowNo);
          186  +                if (re.test(row.Name))
          187  +                    FillPropertyValues(methList.Add(), row);
          188  +            }
          189  +        }
          190  +    }
          191  +    
          192  +    this.sortMethodList(this.form.SortByName);
          193  +}
          194  +
          195  +MethodListForm.prototype.sortMethodList = function (sortByName) {
          196  +    this.form.MethodList.Sort(sortByName ? 'Name' : 'StartLine');
          197  +}
          198  +
          199  +MethodListForm.prototype.saveSettings = function () {
          200  +    this.settings.ReadFromForm(this.form);
          201  +    this.settings.SaveSettings();
          202  +}
          203  +
          204  +////} MethodListForm
          205  +
          206  +////////////////////////////////////////////////////////////////////////////////////////
          207  +////{ CreateMethodStubRefactoring
          208  +////
          209  +
          210  +function CreateMethodStubRefactoring(module) {
          211  +
          212  +    this.module = module;
          213  +    this.textWindow = this.module.textWindow;
          214  +}
          215  +
          216  +CreateMethodStubRefactoring.prototype.refactor = function (selectedText) {
          217  +    
          218  +    var methodName, methodSignature, matches;
          219  +    
          220  +    methodName = this.textWindow.GetWordUnderCursor();
          221  +    if (!methodName)
          222  +        return;
          223  +    
          224  +    var method_call_proc = new RegExp("(?:;\\s*|^\\s*)" + methodName + '(\\(.+?\\))');
          225  +    var method_call_func = new RegExp(methodName + "(\\(.*?\\))");
          226  +    
          227  +    var line = this.textWindow.GetLine(this.textWindow.GetCaretPos().beginRow);
          228  +    
          229  +    var matches = line.match(method_call_proc);
          230  +    var isProc = (matches != null);
          231  +    
          232  +    if (!isProc)
          233  +    {
          234  +        matches = line.match(method_call_func);
          235  +        if (!matches)
          236  +            return;
          237  +    }
          238  +    
          239  +    methodSignature = methodName + matches[1];
          240  +    
          241  +    var procTemplate = "\n"  
          242  +    + "Процедура ИмяМетода()\n"
          243  +    + "\t//TODO: Добавьте исходный код процедуры.\n" 
          244  +    + "КонецПроцедуры\n";
          245  +
          246  +    var funcTemplate = "\n" 
          247  +    + "Функция ИмяМетода()\n"
          248  +    + "\t//TODO: Добавьте исходный код функции.\n" 
          249  +    + "\tВозврат Неопределено;\n"
          250  +    + "КонецФункции\n";
          251  +    
          252  +    var stubCode = isProc ? procTemplate : funcTemplate;
          253  +    stubCode = stubCode.replace('ИмяМетода()', methodSignature);
          254  +    
          255  +    var methodList = new MethodListForm(this.module);
          256  +    if (methodList.selectMethod())
          257  +    {
          258  +        var insertLineIndex = methodList.SelectedMethod.EndLine + 1;
          259  +        this.textWindow.InsertLine(insertLineIndex + 1, stubCode);
          260  +        this.textWindow.SetCaretPos(insertLineIndex + 3, 1);
          261  +    }
          262  +}
          263  +
          264  +////} CreateMethodRefactoring
          265  +
          266  +////////////////////////////////////////////////////////////////////////////////////////
          267  +////{ ExtractMethodRefactoring
          268  +////
          269  +
          270  +function ExtractMethodRefactoring(module) {
          271  +    this.module = module;
          272  +    this.form = loadScriptForm(SelfScript.fullPath.replace(/\.js$/, '.extractMethod.ssf'), this);    
          273  +    this.Params = this.form.Params;
          274  +    this.ReturnValue = this.form.ReturnValue;
          275  +    this.SignaturePreview = this.form.SignaturePreview;
          276  +}
          277  +
          278  +ExtractMethodRefactoring.prototype.getVarRe = function (varName) {
          279  +    return new RegExp("([^\\w\\dА-я\.]|^)" + varName + "([^\\w\\dА-я]|$)", 'i');
          280  +}
          281  +
          282  +ExtractMethodRefactoring.prototype.refactor = function (selectedText) {
          283  +
          284  +    var sel = this.module.textWindow.GetSelection();
          285  +
          286  +    // 0. Определить переменные внутри выделенного блока кода (распарсить его).
          287  +    var extContext = this.getCodeContext(selectedText);
          288  +    var extVars = extContext.AutomaticVars;
          289  +
          290  +    // 1. Определить локальные переменные части кода метода выше выделяемого кода.
          291  +    // 2. Определить параметры метода, из которого выделяется код.
          292  +    var curMethod = this.module.getActiveLineMethod();
          293  +    
          294  +    var codeBefore = this.module.textWindow.Range(curMethod.StartLine, 1, sel.beginRow-1).GetText();
          295  +    var contextBefore = this.getCodeContext(codeBefore);
          296  +
          297  +    // 3. Определить, какие 1+2 инициализируются в 0 (AutomaticVars), а какие используются 
          298  +    this.fillParams(contextBefore.AutomaticVars, extVars, selectedText);    
          299  +    this.fillParams(curMethod.Params, extVars, selectedText);    
          300  +        
          301  +    // 4. Те переменные, которые используются в остальной части кода - возвращаемые значения.
          302  +    var codeAfter = this.module.textWindow.Range(sel.endRow + 1, 1, curMethod.EndLine).GetText();
          303  +    var contextAfter = this.getCodeContext(codeAfter);
          304  +    
          305  +    this.fillReturnValues(contextAfter.AutomaticVars, extVars, codeAfter);
          306  +        
          307  +    if (this.form.DoModal())
          308  +        this.extractMethod(selectedText);
          309  +}
          310  +
          311  +ExtractMethodRefactoring.prototype.fillParams = function (extArgs, extVars, source) {
          312  +    for (var i=0; i<extArgs.length; i++)
          313  +    {
          314  +        var varName = extArgs[i];
          315  +        var re = this.getVarRe(varName);
          316  +        if (re.test(source) && extVars.indexOf(varName) == -1)
          317  +            this.addParam(varName, true, false);
          318  +    }
          319  +}
          320  +
          321  +ExtractMethodRefactoring.prototype.fillReturnValues = function (extArgs, extVars, source) {
          322  +    //debugger;
          323  +    for (var i=0; i<extVars.length; i++)
          324  +    {
          325  +        var varName = extVars[i];
          326  +        var re = this.getVarRe(varName);
          327  +        if (re.test(source) && extArgs.indexOf(varName) == -1)
          328  +            this.addReturnValue(varName);
          329  +    }
          330  +}
          331  +
          332  +ExtractMethodRefactoring.prototype.getCodeContext = function (code) {
          333  +    var extractedCode = "Процедура ВыделенныйМетод()\n" + code + "\nКонецПроцедуры";
          334  +    var extractedContext = SyntaxAnalysis.AnalyseModule(extractedCode, false);
          335  +    return extractedContext.getMethodByName("ВыделенныйМетод");
          336  +}
          337  +
          338  +ExtractMethodRefactoring.prototype.addParam = function (paramName, isParam, isVal) {
          339  +    if (!this.Params.Find(paramName, 'Name'))
          340  +    {
          341  +        var paramRow = this.Params.Add();
          342  +        paramRow.Name = paramName;
          343  +        paramRow.isParam = isParam ? true : false;
          344  +        paramRow.isVal = isVal ? true : false;
          345  +    }
          346  +}
          347  +
          348  +ExtractMethodRefactoring.prototype.addReturnValue = function (varName) {
          349  +    if (!this.ReturnValue.Find(varName, 'Name'))
          350  +    {
          351  +        var row = this.ReturnValue.Add();
          352  +        row.Name = varName;
          353  +    }
          354  +}
          355  +
          356  +ExtractMethodRefactoring.prototype.BtOKClick = function (Control) {
          357  +
          358  +    if (!this.form.Name.match(/^[_\wА-я](?:[_\w\dА-я]*)$/))
          359  +    {
          360  +        DoMessageBox("Имя метода должно быть правильным идентификатором!");
          361  +        return;
          362  +    }    
          363  +    
          364  +    this.form.Close(true);
          365  +}
          366  +
          367  +ExtractMethodRefactoring.prototype.BtCancelClick = function (Control) {
          368  +    this.form.Close(false);
          369  +}
          370  +
          371  +ExtractMethodRefactoring.prototype.extractMethod = function(source) {
          372  +
          373  +    var tw = this.module.textWindow;
          374  +    var sel = tw.GetSelection();
          375  +
          376  +    var params = new Array;
          377  +    for (var i=0; i<this.Params.Count(); i++)
          378  +    {
          379  +        var paramRow = this.Params.Get(i);
          380  +        if (paramRow.IsParam)
          381  +            params.push((paramRow.IsVal ? 'Знач ' : '') + paramRow.Name);
          382  +    }
          383  +    
          384  +    // Откорректируем отступ.
          385  +    var srcIndent = StringUtils.getIndent(source);
          386  +    source = StringUtils.shiftLeft(source, srcIndent);
          387  +    source = StringUtils.shiftRight(source, "\t");
          388  +    
          389  +    // Сформируем исходный код определения выделенного метода.
          390  +    var newMethod = this.form.IsProc ? 'Процедура' : 'Функция';
          391  +    newMethod += ' ' + this.form.Name + '(' + params.join(', ') + ')';
          392  +    if (this.form.Exported)
          393  +        newMethod += " Экспорт";   
          394  +        
          395  +    newMethod += "\n\n" + this.prepareSource(source) + "\n\n";  
          396  +    
          397  +    if (this.form.IsProc) 
          398  +    {
          399  +        newMethod += 'КонецПроцедуры';        
          400  +        
          401  +    }
          402  +    else
          403  +    {
          404  +        var retVal = "Неопределено";
          405  +        if (this.ReturnValue.Count() > 0) {
          406  +            retVal = this.ReturnValue.Get(0).Name;
          407  +        }
          408  +        newMethod += "\tВозврат " + retVal + ";";    
          409  +        newMethod += "\n\n" + 'КонецФункции';    
          410  +    }
          411  +
          412  +    // Получим метод, внутри которого мы находимся.
          413  +    var curMethod = this.module.getActiveLineMethod();
          414  +    
          415  +    // Добавим в модуль определение выделенного метода.
          416  +    tw.InsertLine(curMethod.EndLine + 2, "\n" + newMethod);
          417  +        
          418  +    // Заменим выделенный код на вызов нового метода.
          419  +    var methCall = this.form.Name + '(' + params.join(', ') + ");\n";
          420  +    
          421  +    if (!this.form.IsProc && this.ReturnValue.Count() > 0) {
          422  +        retVal = this.ReturnValue.Get(0).Name;
          423  +        methCall = retVal + ' = ' + methCall;
          424  +    }    
          425  +    
          426  +    tw.SetSelection(sel.beginRow, sel.beginCol, sel.endRow, sel.endCol);
          427  +    tw.SetSelectedText(srcIndent + methCall);    
          428  +}
          429  +
          430  +ExtractMethodRefactoring.prototype.prepareSource = function(source) {
          431  +
          432  +    var lines = StringUtils.toLines(source);
          433  +    if (lines.length < 2)
          434  +        return source;
          435  +        
          436  +    var startIndex = 0;
          437  +    while (startIndex < lines.length && lines[startIndex].match(/^\s*$/))
          438  +        startIndex++;
          439  +
          440  +    var endIndex = lines.length - 1;
          441  +    while (endIndex > 0 && lines[endIndex].match(/^\s*$/))
          442  +        endIndex--;
          443  +        
          444  +    if (startIndex <= endIndex)
          445  +        return StringUtils.fromLines(lines.splice(startIndex, endIndex - startIndex + 1));
          446  +                        
          447  +    return source;
          448  +}
          449  +
          450  +////} ExtractMethodRefactoring
          451  +
          452  +////////////////////////////////////////////////////////////////////////////////////////
          453  +////{ TextChangesWatcher (Александр Орефков)
          454  +////
          455  +
          456  +// Класс для отслеживания изменения текста в поле ввода, для замены
          457  +// события АвтоПодборТекста. Штатное событие плохо тем, что не возникает
          458  +// - при установке пустого текста
          459  +// - при изменении текста путем вставки/вырезания из/в буфера обмена
          460  +// - при отмене редактирования (Ctrl+Z)
          461  +// не позволяет регулировать задержку
          462  +// Параметры конструктора
          463  +// field - элемент управления поле ввода, чье изменение хотим отслеживать
          464  +// ticks - величина задержки после ввода текста в десятых секунды (т.е. 3 - 300 мсек)
          465  +// invoker - функция обратного вызова, вызывается после окончания изменения текста,
          466  +//  новый текст передается параметром функции
          467  +function TextChangesWatcher(field, ticks, invoker)
          468  +{
          469  +    this.ticks = ticks
          470  +    this.invoker = invoker
          471  +    this.field = field
          472  +}
          473  +
          474  +// Начать отслеживание изменения текста
          475  +TextChangesWatcher.prototype.start = function()
          476  +{
          477  +    this.lastText = this.field.Значение.replace(/^\s*|\s*$/g, '').toLowerCase()
          478  +    this.noChangesTicks = 0
          479  +    this.timerID = createTimer(100, this, "onTimer")
          480  +}
          481  +// Остановить отслеживание изменения текста
          482  +TextChangesWatcher.prototype.stop = function()
          483  +{
          484  +    killTimer(this.timerID)
          485  +}
          486  +// Обработчик события таймера
          487  +TextChangesWatcher.prototype.onTimer = function()
          488  +{
          489  +    // Получим текущий текст из поля ввода
          490  +    vbs.var0 = this.field
          491  +    vbs.DoExecute("var0.GetTextSelectionBounds var1, var2, var3, var4")
          492  +    this.field.УстановитьГраницыВыделения(1, 1, 1, 10000)
          493  +    var newText = this.field.ВыделенныйТекст.replace(/^\s*|\s*$/g, '').toLowerCase()
          494  +    this.field.УстановитьГраницыВыделения(vbs.var1, vbs.var2, vbs.var3, vbs.var4)
          495  +    // Проверим, изменился ли текст по сравению с прошлым разом
          496  +    if(newText != this.lastText)
          497  +    {
          498  +        // изменился, запомним его
          499  +        this.lastText = newText
          500  +        this.noChangesTicks = 0
          501  +    }
          502  +    else
          503  +    {
          504  +        // Текст не изменился. Если мы еще не сигнализировали об этом, то увеличим счетчик тиков
          505  +        if(this.noChangesTicks <= this.ticks)
          506  +        {
          507  +            if(++this.noChangesTicks > this.ticks)  // Достигли заданного количества тиков.
          508  +                this.invoker(newText)               // Отрапортуем
          509  +        }
          510  +    }
          511  +}
          512  +
          513  +////
          514  +////} TextChangesWatcher (Александр Орефков)
          515  +////////////////////////////////////////////////////////////////////////////////////////
          516  +
          517  +////////////////////////////////////////////////////////////////////////////////////////
          518  +////{ Вспомогательные функции
          519  +////
          520  +
          521  +
          522  +
          523  +////} Вспомогательные функции

Added refactoring.methodList.ssf.

cannot compute difference between binary files