This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 256404 - Introduced variable shadowing a field leads to change of behavior and compile error
Summary: Introduced variable shadowing a field leads to change of behavior and compile...
Status: RESOLVED FIXED
Alias: None
Product: java
Classification: Unclassified
Component: Hints (show other bugs)
Version: 8.2
Hardware: PC Windows 7
: P3 normal (vote)
Assignee: Svata Dedic
URL:
Keywords:
Depends on: 262281
Blocks:
  Show dependency tree
 
Reported: 2015-11-06 10:16 UTC by Jachym_Vojtek
Modified: 2016-06-18 03:11 UTC (History)
0 users

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jachym_Vojtek 2015-11-06 10:16:10 UTC
1) Create Java file
package pck;

public class IntroduceVariable {
    /*static */ long currentTime = 42;

    void foo() {
        System.out.println(System.currentTimeMillis()); // #7
        System.out.println(System.currentTimeMillis());
        System.currentTimeMillis();

        long i = currentTime;
        System.out.println(currentTime);

        class MyLocalClass {
            String s = "" + currentTime;

            {
                System.out.println(System.currentTimeMillis());
                System.out.println(currentTime);
            }
        }
    }
}

2) Place cursor within currentTimeMillis() method call on line 7, right click->Refactor->Introduce->Variable...
Confirm selection of "System.currentTimeMillis()".

Introduce Variable dialog
Name: currentTime
Replace All Occurences (4) - check
OK


The resulting code (with my comments on wrong replacements) is:
package pck;

public class IntroduceVariable {
    /*static */ long currentTime = 42;

    void foo() {
        long currentTime = System.currentTimeMillis();
        System.out.println(currentTime); // #7
        System.out.println(currentTime);
        currentTime; // Not a statement. Expression statements cannot be replaced by a variable name.

        long i = currentTime; // This should be this.currentTime (if the field is instance field), in case of static field -> IntroduceVariable.currentTime
        System.out.println(currentTime); // This should be this.currentTime (if the field is instance field), in case of static field -> IntroduceVariable.currentTime

        class MyLocalClass {
            String s = "" + currentTime; //This should be IntroduceVariable.this.currentTime (if the field is instance field), in case of static field -> IntroduceVariable.currentTime

            {
                System.out.println(currentTime); // OK
                System.out.println(currentTime); //This should be IntroduceVariable.this.currentTime (if the field is instance field), in case of static field -> IntroduceVariable.currentTime
            }
        }
    }
}

When fixing this, please considered also possibility that class MyLocalClass can declare its own field currentTime:
class MyLocalClass {
  String currentTime = "Hello";
  String s = "" + currentTime; 
  ...
}
Comment 1 Svata Dedic 2015-11-09 14:17:19 UTC
Breaks code, bumping priority.
Comment 2 Jachym_Vojtek 2015-11-16 15:46:41 UTC
One more example class you can use for testing so that the scope qualifier of outer classes is prefixed properly.
Enjoy:

package pck;

public class CheckFieldShadowing {
    int i = 9;        
    
    class InnerClass extends ParentClassForShadowing {
        
        class InnerInnerClass {
            void foo() {
                // Introduce variable for 'System.currentTimeMillis()', 
                // use names: 'x', 'y', 'z,',' i'
                System.out.println(System.currentTimeMillis()); 
                System.out.println(x);
                System.out.println(y);
                System.out.println(z);
                System.out.println(i);
            }   
        }
    }
}

class ParentClassForShadowing extends SuperParentClass implements SuperInterface {
    public int x;
}

class SuperParentClass {
    protected int y;
}

interface SuperInterface {
    static int z = 3;
}
Comment 3 Svata Dedic 2016-01-06 15:59:30 UTC
I don't think I can fix the behaviour change without some additional metadata (the same case would be a Math.random() call assigned to a variable). 

But replacement of the method call statement with expression (which is not a proper statement) can be fixed. Not a P2, though.
Comment 4 Svata Dedic 2016-05-31 14:56:36 UTC
Adding dependency; I need to find the to-be-shadowed definitions.
Comment 5 Svata Dedic 2016-06-17 08:48:27 UTC
Fixed in jet-main#a494d90e587c
Comment 6 Quality Engineering 2016-06-18 03:11:10 UTC
Integrated into 'main-silver', will be available in build *201606180002* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress)

Changeset: http://hg.netbeans.org/main-silver/rev/a494d90e587c
User: Svata Dedic <sdedic@netbeans.org>
Log: #256404: UI warns if a symbol should be shadowed; refactors references, if the user insists on shadowing