ruby/src/org/netbeans/modules/ruby/RubyRenameHandler.java
author enebo@netbeans.org
Sun, 08 Dec 2013 12:20:16 -0600
changeset 4555 3773928e70d0
parent 4554 07958c1ff402
child 4556 e276e451257b
permissions -rw-r--r--
Let jruby-parser figure out occurrences and delete netbeans logic for this
tor@1
     1
/*
phrebejk@559
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
tor@1
     3
 *
jglick@4117
     4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
jglick@4117
     5
 *
jglick@4117
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jglick@4117
     7
 * Other names may be trademarks of their respective owners.
tor@1
     8
 *
phrebejk@559
     9
 * The contents of this file are subject to the terms of either the GNU
phrebejk@559
    10
 * General Public License Version 2 only ("GPL") or the Common
phrebejk@559
    11
 * Development and Distribution License("CDDL") (collectively, the
phrebejk@559
    12
 * "License"). You may not use this file except in compliance with the
phrebejk@559
    13
 * License. You can obtain a copy of the License at
phrebejk@559
    14
 * http://www.netbeans.org/cddl-gplv2.html
phrebejk@559
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
phrebejk@559
    16
 * specific language governing permissions and limitations under the
phrebejk@559
    17
 * License.  When distributing the software, include this License Header
phrebejk@559
    18
 * Notice in each file and include the License file at
jglick@4117
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
phrebejk@559
    20
 * particular file as subject to the "Classpath" exception as provided
jglick@4117
    21
 * by Oracle in the GPL Version 2 section of the License file that
phrebejk@559
    22
 * accompanied this code. If applicable, add the following below the
phrebejk@559
    23
 * License Header, with the fields enclosed by brackets [] replaced by
phrebejk@559
    24
 * your own identifying information:
tor@1
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
tor@1
    26
 *
phrebejk@559
    27
 * Contributor(s):
phrebejk@559
    28
 *
tor@1
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
tor@1
    30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
tor@1
    31
 * Microsystems, Inc. All Rights Reserved.
phrebejk@559
    32
 *
phrebejk@559
    33
 * If you wish your version of this file to be governed by only the CDDL
phrebejk@559
    34
 * or only the GPL Version 2, indicate your decision by adding
phrebejk@559
    35
 * "[Contributor] elects to include this software in this distribution
phrebejk@559
    36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
phrebejk@559
    37
 * single choice of license, a recipient has the option to distribute
phrebejk@559
    38
 * your version of this file under either the CDDL, the GPL Version 2 or
phrebejk@559
    39
 * to extend the choice of license to its licensees as provided above.
phrebejk@559
    40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
phrebejk@559
    41
 * Version 2 license, then the option applies only if the new code is
phrebejk@559
    42
 * made subject to such option by the copyright holder.
tor@1
    43
 */
tor@1
    44
package org.netbeans.modules.ruby;
tor@1
    45
tor@1
    46
import java.util.Collections;
tor@1
    47
import java.util.HashSet;
tor@1
    48
import java.util.Set;
tor@1
    49
emononen@3259
    50
import org.jrubyparser.ast.Node;
enebo@4520
    51
import org.jrubyparser.ast.ILocalVariable;
mkrauskopf@3030
    52
import org.netbeans.modules.csl.api.InstantRenamer;
mkrauskopf@3030
    53
import org.netbeans.modules.csl.api.OffsetRange;
mkrauskopf@3030
    54
import org.netbeans.modules.csl.spi.ParserResult;
tor@544
    55
import org.netbeans.modules.ruby.lexer.LexUtilities;
tor@1
    56
import org.openide.util.NbBundle;
tor@1
    57
tor@1
    58
/**
tor@1
    59
 * Handle renaming of local elements
tor@1
    60
 * @todo I should be able to rename top-level methods as well since they
tor@1
    61
 *   are private
tor@544
    62
 * @todo Rename |j| in the following will only rename "j" inside the block!
tor@544
    63
 * <pre>
tor@544
    64
i = 50
tor@544
    65
j = 200
tor@544
    66
k = 100
tor@544
    67
x = [1,2,3]
tor@544
    68
x.each do |j|
tor@544
    69
  puts j
tor@544
    70
end
tor@544
    71
puts j
tor@544
    72
 * </pre>
tor@544
    73
 * @todo When you fix, make sure BlockarReuse is also fixed!
tor@544
    74
 * @todo Try renaming "hello" in the exception here; my code is confused
tor@544
    75
 *   about what I'm renaming (aliases method name) and the refactoring dialog
tor@544
    76
 *   name is wrong! This is happening because it's also changing GlobalAsgnNode for $!
tor@544
    77
 *   but its parent is LocalAsgnNode, and -its- -grand- parent is a RescueBodyNode! 
tor@544
    78
 *   I should special case this!
tor@544
    79
 * <pre>
tor@544
    80
def hello
tor@544
    81
  begin
tor@544
    82
    ex = 50
tor@544
    83
    puts "test"
tor@544
    84
  
tor@544
    85
  rescue Exception => hello
tor@544
    86
    puts hello
tor@544
    87
  end
tor@544
    88
end
tor@544
    89
 *
tor@544
    90
 * </pre>
tor@1
    91
 *
tor@1
    92
 * @author Tor Norbye
tor@1
    93
 */
tor@1719
    94
public class RubyRenameHandler implements InstantRenamer {
mkrauskopf@3030
    95
    
tor@1719
    96
    public RubyRenameHandler() {
tor@1
    97
    }
tor@1
    98
enebo@4519
    99
    @Override
enebo@4519
   100
    public boolean isRenameAllowed(ParserResult info, int caretOffset, String[] explanationRetValue) {
tor@1
   101
        Node root = AstUtilities.getRoot(info);
tor@1
   102
tor@1
   103
        if (root == null) {
tor@1719
   104
            explanationRetValue[0] = NbBundle.getMessage(RubyRenameHandler.class, "NoRenameWithErrors");
tor@1
   105
            return false;
tor@1
   106
        }
tor@1
   107
enebo@4520
   108
        Node closest = root.getNodeAt(AstUtilities.getAstOffset(info, caretOffset));
enebo@4519
   109
        if (closest == null) return false;
enebo@4520
   110
        if (closest instanceof ILocalVariable) return true;  // All local block/method vars can be renamed
tor@1
   111
emononen@3259
   112
        switch (closest.getNodeType()) {
enebo@4520
   113
        case INSTASGNNODE: case INSTVARNODE: case CLASSVARDECLNODE: case CLASSVARNODE: case CLASSVARASGNNODE:
enebo@4520
   114
        case GLOBALASGNNODE: case GLOBALVARNODE: case CONSTDECLNODE: case CONSTNODE: case DEFNNODE: case DEFSNODE:
enebo@4520
   115
        case FCALLNODE: case CALLNODE: case VCALLNODE: case COLON2NODE: case COLON3NODE: case ALIASNODE:
enebo@4520
   116
        case SYMBOLNODE: // TODO - what about the string arguments in an alias node? Gotta check those
tor@1
   117
            return true;
tor@1
   118
        }
tor@1
   119
tor@1
   120
        return false;
tor@1
   121
    }
tor@1
   122
enebo@4519
   123
    @Override
mkrauskopf@3030
   124
    public Set<OffsetRange> getRenameRegions(ParserResult info, int caretOffset) {
enebo@4555
   125
        Node closest = AstUtilities.findNodeAtOffset(info, caretOffset);
enebo@4555
   126
        if (closest == null || !(closest instanceof ILocalVariable)) return Collections.emptySet();
tor@1
   127
enebo@4555
   128
        ILocalVariable variable = (ILocalVariable) closest;
tor@1
   129
        Set<OffsetRange> regions = new HashSet<OffsetRange>();
tor@1
   130
enebo@4555
   131
        for (ILocalVariable occurrence: variable.getOccurrences()) {
enebo@4555
   132
            OffsetRange range = LexUtilities.getLexerOffsets(info, 
enebo@4555
   133
                    AstUtilities.offsetRangeFor(occurrence.getNamePosition()));
tor@544
   134
enebo@4555
   135
            if (range != OffsetRange.NONE) regions.add(range);
tor@1
   136
        }
tor@1
   137
tor@1
   138
        return regions;
tor@1
   139
    }
tor@1
   140
tor@681
   141
    // TODO: Check
tor@681
   142
    //  quick tip renaming
tor@681
   143
    //  unused detection
tor@681
   144
    //  occurrences marking
tor@681
   145
    //  code completion
tor@681
   146
    //  live code templates
tor@681
   147
    // ...anyone else who calls findBlock
tor@681
   148
    //
tor@681
   149
    // Test both parent blocks, sibling blocks and descendant blocks
tor@681
   150
    // Make sure the "isUsed" detection is smarter too.
tor@1
   151
}