This repository has been archived on 2023-06-18. You can view files and clone it, but cannot push or open issues or pull requests.
ima02/resources/defects4j-checkout-closure-1f/test/com/google/javascript/jscomp/RenameVarsTest.java

598 lines
21 KiB
Java
Raw Permalink Normal View History

2023-04-25 11:33:41 +00:00
/*
* Copyright 2005 The Closure Compiler Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.javascript.rhino.Node;
import java.util.*;
/**
* Tests for {@link RenameVars}.
*/
public class RenameVarsTest extends CompilerTestCase {
private static final String DEFAULT_PREFIX = "";
private String prefix = DEFAULT_PREFIX;
private VariableMap previouslyUsedMap =
new VariableMap(ImmutableMap.<String, String>of());
private RenameVars renameVars;
private boolean withClosurePass = false;
private boolean localRenamingOnly = false;
private boolean preserveFunctionExpressionNames = false;
private boolean useGoogleCodingConvention = true;
private boolean generatePseudoNames = false;
private boolean shouldShadow = false;
@Override
protected CodingConvention getCodingConvention() {
if (useGoogleCodingConvention) {
return new GoogleCodingConvention();
} else {
return CodingConventions.getDefault();
}
}
@Override
protected CompilerPass getProcessor(Compiler compiler) {
if (withClosurePass) {
return new ClosurePassAndRenameVars(compiler);
} else {
return renameVars = new RenameVars(compiler, prefix,
localRenamingOnly, preserveFunctionExpressionNames,
generatePseudoNames, shouldShadow,
previouslyUsedMap, null, null);
}
}
@Override
protected int getNumRepetitions() {
return 1;
}
@Override
protected void setUp() throws Exception {
super.setUp();
previouslyUsedMap = new VariableMap(ImmutableMap.<String, String>of());
prefix = DEFAULT_PREFIX;
withClosurePass = false;
localRenamingOnly = false;
preserveFunctionExpressionNames = false;
generatePseudoNames = false;
shouldShadow = false;
// TODO(johnlenz): Enable Normalize during these tests.
}
public void testRenameSimple() {
test("function Foo(v1, v2) {return v1;} Foo();",
"function a(b, c) {return b;} a();");
}
public void testRenameGlobals() {
test("var Foo; var Bar, y; function x() { Bar++; }",
"var a; var b, c; function d() { b++; }");
}
public void testRenameLocals() {
test("(function (v1, v2) {}); (function (v3, v4) {});",
"(function (a, b) {}); (function (a, b) {});");
test("function f1(v1, v2) {}; function f2(v3, v4) {};",
"function c(a, b) {}; function d(a, b) {};");
}
public void testRenameRedeclaredGlobals() {
test("function f1(v1, v2) {f1()};" +
"/** @suppress {duplicate} */" +
"function f1(v3, v4) {f1()};",
"function a(b, c) {a()};" +
"function a(b, c) {a()};");
localRenamingOnly = true;
test("function f1(v1, v2) {f1()};" +
"/** @suppress {duplicate} */" +
"function f1(v3, v4) {f1()};",
"function f1(a, b) {f1()};" +
"function f1(a, b) {f1()};");
}
public void testRecursiveFunctions1() {
test("var walk = function walk(node, aFunction) {" +
" walk(node, aFunction);" +
"};",
"var a = function a(b, c) {" +
" a(b, c);" +
"};");
localRenamingOnly = true;
test("var walk = function walk(node, aFunction) {" +
" walk(node, aFunction);" +
"};",
"var walk = function walk(a, b) {" +
" walk(a, b);" +
"};");
}
public void testRecursiveFunctions2() {
preserveFunctionExpressionNames = true;
test("var walk = function walk(node, aFunction) {" +
" walk(node, aFunction);" +
"};",
"var c = function walk(a, b) {" +
" walk(a, b);" +
"};");
localRenamingOnly = true;
test("var walk = function walk(node, aFunction) {" +
" walk(node, aFunction);" +
"};",
"var walk = function walk(a, b) {" +
" walk(a, b);" +
"};");
}
public void testRenameLocalsClashingWithGlobals() {
test("function a(v1, v2) {return v1;} a();",
"function a(b, c) {return b;} a();");
}
public void testRenameNested() {
test("function f1(v1, v2) { (function(v3, v4) {}) }",
"function a(b, c) { (function(d, e) {}) }");
test("function f1(v1, v2) { function f2(v3, v4) {} }",
"function a(b, c) { function d(e, f) {} }");
}
public void testBleedingRecursiveFunctions1() {
// On IE, bleeding functions will interfere with each other if
// they are in the same scope. In the below example, we want to be
// sure that a and b get separate names.
test("var x = function a(x) { return x ? 1 : a(1); };" +
"var y = function b(x) { return x ? 2 : b(2); };",
"var c = function b(a) { return a ? 1 : b(1); };" +
"var e = function d(a) { return a ? 2 : d(2); };");
}
public void testBleedingRecursiveFunctions2() {
test("function f() {" +
" var x = function a(x) { return x ? 1 : a(1); };" +
" var y = function b(x) { return x ? 2 : b(2); };" +
"}",
"function d() {" +
" var e = function b(a) { return a ? 1 : b(1); };" +
" var f = function a(c) { return c ? 2 : a(2); };" +
"}");
}
public void testBleedingRecursiveFunctions3() {
test("function f() {" +
" var x = function a(x) { return x ? 1 : a(1); };" +
" var y = function b(x) { return x ? 2 : b(2); };" +
" var z = function c(x) { return x ? y : c(2); };" +
"}",
"function f() {" +
" var g = function c(a) { return a ? 1 : c(1); };" +
" var d = function a(b) { return b ? 2 : a(2); };" +
" var h = function b(e) { return e ? d : b(2); };" +
"}");
}
public void testRenameWithExterns1() {
String externs = "var foo;";
test(externs, "var bar; foo(bar);", "var a; foo(a);", null, null);
}
public void testRenameWithExterns2() {
String externs = "var a;";
test(externs, "var b = 5", "var b = 5", null, null);
}
public void testDoNotRenameExportedName() {
test("_foo()", "_foo()");
}
public void testRenameWithNameOverlap() {
test("var a = 1; var b = 2; b + b;",
"var a = 1; var b = 2; b + b;");
}
public void testRenameWithPrefix1() {
prefix = "PRE_";
test("function Foo(v1, v2) {return v1} Foo();",
"function PRE_(a, b) {return a} PRE_();");
prefix = DEFAULT_PREFIX;
}
public void testRenameWithPrefix2() {
prefix = "PRE_";
test("function Foo(v1, v2) {var v3 = v1 + v2; return v3;} Foo();",
"function PRE_(a, b) {var c = a + b; return c;} PRE_();");
prefix = DEFAULT_PREFIX;
}
public void testRenameWithPrefix3() {
prefix = "a";
test("function Foo() {return 1;}" +
"function Bar() {" +
" var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z," +
" A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,aa,ab;" +
" Foo();" +
"} Bar();",
"function a() {return 1;}" +
"function aa() {" +
" var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A," +
" B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,ba,ca;" +
" a();" +
"} aa();");
prefix = DEFAULT_PREFIX;
}
public void testNamingBasedOnOrderOfOccurrence() {
test("var q,p,m,n,l,k; " +
"(function (r) {}); try { } catch(s) {}; var t = q + q;",
"var a,b,c,d,e,f; " +
"(function(g) {}); try { } catch(h) {}; var i = a + a;"
);
test("(function(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z," +
"a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,$){});" +
"var a4,a3,a2,a1,b4,b3,b2,b1,ab,ac,ad,fg;function foo(){};",
"(function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z," +
"A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$){});" +
"var aa,ba,ca,da,ea,fa,ga,ha,ia,ja,ka,la;function ma(){};");
}
public void testStableRenameSimple() {
VariableMap expectedVariableMap = makeVariableMap(
"Foo", "a", "L 0", "b", "L 1", "c");
testRenameMap("function Foo(v1, v2) {return v1;} Foo();",
"function a(b, c) {return b;} a();", expectedVariableMap);
expectedVariableMap = makeVariableMap(
"Foo", "a", "L 0", "b", "L 1", "c", "L 2", "d");
testRenameMapUsingOldMap("function Foo(v1, v2, v3) {return v1;} Foo();",
"function a(b, c, d) {return b;} a();", expectedVariableMap);
}
public void testStableRenameGlobals() {
VariableMap expectedVariableMap = makeVariableMap(
"Foo", "a", "Bar", "b", "y", "c", "x", "d");
testRenameMap("var Foo; var Bar, y; function x() { Bar++; }",
"var a; var b, c; function d() { b++; }",
expectedVariableMap);
expectedVariableMap = makeVariableMap(
"Foo", "a", "Bar", "b", "y", "c", "x", "d", "Baz", "f", "L 0" , "e");
testRenameMapUsingOldMap(
"var Foo, Baz; var Bar, y; function x(R) { return R + Bar++; }",
"var a, f; var b, c; function d(e) { return e + b++; }",
expectedVariableMap);
}
public void testStableRenameWithPointlesslyAnonymousFunctions() {
VariableMap expectedVariableMap = makeVariableMap("L 0", "a", "L 1", "b");
testRenameMap("(function (v1, v2) {}); (function (v3, v4) {});",
"(function (a, b) {}); (function (a, b) {});",
expectedVariableMap);
expectedVariableMap = makeVariableMap("L 0", "a", "L 1", "b", "L 2", "c");
testRenameMapUsingOldMap("(function (v0, v1, v2) {});" +
"(function (v3, v4) {});",
"(function (a, b, c) {});" +
"(function (a, b) {});",
expectedVariableMap);
}
public void testStableRenameLocalsClashingWithGlobals() {
test("function a(v1, v2) {return v1;} a();",
"function a(b, c) {return b;} a();");
previouslyUsedMap = renameVars.getVariableMap();
test("function bar(){return;}function a(v1, v2) {return v1;} a();",
"function d(){return;}function a(b, c) {return b;} a();");
}
public void testStableRenameNested() {
VariableMap expectedVariableMap = makeVariableMap(
"f1", "a", "L 0", "b", "L 1", "c", "L 2", "d", "L 3", "e");
testRenameMap("function f1(v1, v2) { (function(v3, v4) {}) }",
"function a(b, c) { (function(d, e) {}) }",
expectedVariableMap);
expectedVariableMap = makeVariableMap(
"f1", "a", "L 0", "b", "L 1", "c", "L 2", "d", "L 3", "e", "L 4", "f");
testRenameMapUsingOldMap(
"function f1(v1, v2) { (function(v3, v4, v5) {}) }",
"function a(b, c) { (function(d, e, f) {}) }",
expectedVariableMap);
}
public void testStableRenameWithExterns1() {
String externs = "var foo;";
test(externs, "var bar; foo(bar);", "var a; foo(a);", null, null);
previouslyUsedMap = renameVars.getVariableMap();
test(externs, "var bar, baz; foo(bar, baz);",
"var a, b; foo(a, b);", null, null);
}
public void testStableRenameWithExterns2() {
String externs = "var a;";
test(externs, "var b = 5", "var b = 5", null, null);
previouslyUsedMap = renameVars.getVariableMap();
test(externs, "var b = 5, catty = 9;", "var b = 5, c=9;", null, null);
}
public void testStableRenameWithNameOverlap() {
test("var a = 1; var b = 2; b + b;",
"var a = 1; var b = 2; b + b;");
previouslyUsedMap = renameVars.getVariableMap();
test("var a = 1; var c, b = 2; b + b;",
"var a = 1; var c, b = 2; b + b;");
}
public void testStableRenameWithAnonymousFunctions() {
VariableMap expectedVariableMap = makeVariableMap("L 0", "a", "foo", "b");
testRenameMap("function foo(bar){return bar;}foo(function(h){return h;});",
"function b(a){return a}b(function(a){return a;})",
expectedVariableMap);
expectedVariableMap = makeVariableMap("foo", "b", "L 0", "a", "L 1", "c");
testRenameMapUsingOldMap(
"function foo(bar) {return bar;}foo(function(g,h) {return g+h;});",
"function b(a){return a}b(function(a,c){return a+c;})",
expectedVariableMap);
}
public void testStableRenameSimpleExternsChanges() {
VariableMap expectedVariableMap = makeVariableMap(
"Foo", "a", "L 0", "b", "L 1", "c");
testRenameMap("function Foo(v1, v2) {return v1;} Foo();",
"function a(b, c) {return b;} a();", expectedVariableMap);
expectedVariableMap = makeVariableMap("L 0", "b", "L 1", "c", "L 2", "a");
String externs = "var Foo;";
testRenameMapUsingOldMap(externs,
"function Foo(v1, v2, v0) {return v1;} Foo();",
"function Foo(b, c, a) {return b;} Foo();",
expectedVariableMap);
}
public void testStableRenameSimpleLocalNameExterned() {
test("function Foo(v1, v2) {return v1;} Foo();",
"function a(b, c) {return b;} a();");
previouslyUsedMap = renameVars.getVariableMap();
String externs = "var b;";
test(externs, "function Foo(v1, v2) {return v1;} Foo(b);",
"function a(d, c) {return d;} a(b);", null, null);
}
public void testStableRenameSimpleGlobalNameExterned() {
test("function Foo(v1, v2) {return v1;} Foo();",
"function a(b, c) {return b;} a();");
previouslyUsedMap = renameVars.getVariableMap();
String externs = "var Foo;";
test(externs, "function Foo(v1, v2, v0) {return v1;} Foo();",
"function Foo(b, c, a) {return b;} Foo();", null, null);
}
public void testStableRenameWithPrefix1AndUnstableLocalNames() {
prefix = "PRE_";
test("function Foo(v1, v2) {return v1} Foo();",
"function PRE_(a, b) {return a} PRE_();");
previouslyUsedMap = renameVars.getVariableMap();
prefix = "PRE_";
test("function Foo(v0, v1, v2) {return v1} Foo();",
"function PRE_(a, b, c) {return b} PRE_();");
}
public void testStableRenameWithPrefix2() {
prefix = "a";
test("function Foo() {return 1;}" +
"function Bar() {" +
" var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z," +
" A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,aa,ab;" +
" Foo();" +
"} Bar();",
"function a() {return 1;}" +
"function aa() {" +
" var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A," +
" B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,ba,ca;" +
" a();" +
"} aa();");
previouslyUsedMap = renameVars.getVariableMap();
prefix = "a";
test("function Foo() {return 1;}" +
"function Baz() {return 1;}" +
"function Bar() {" +
" var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z," +
" A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,aa,ab;" +
" Foo();" +
"} Bar();",
"function a() {return 1;}" +
"function ab() {return 1;}" +
"function aa() {" +
" var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A," +
" B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,ba,ca;" +
" a();" +
"} aa();");
}
public void testContrivedExampleWhereConsistentRenamingIsWorse() {
previouslyUsedMap = makeVariableMap(
"Foo", "LongString", "L 0", "b", "L 1", "c");
test("function Foo(v1, v2) {return v1;} Foo();",
"function LongString(b, c) {return b;} LongString();");
previouslyUsedMap = renameVars.getVariableMap();
VariableMap expectedVariableMap = makeVariableMap(
"Foo", "LongString", "L 0", "b", "L 1", "c");
assertVariableMapsEqual(expectedVariableMap, previouslyUsedMap);
}
public void testExportSimpleSymbolReservesName() {
test("var goog, x; goog.exportSymbol('a', x);",
"var a, b; a.exportSymbol('a', b);");
withClosurePass = true;
test("var goog, x; goog.exportSymbol('a', x);",
"var b, c; b.exportSymbol('a', c);");
}
public void testExportComplexSymbolReservesName() {
test("var goog, x; goog.exportSymbol('a.b', x);",
"var a, b; a.exportSymbol('a.b', b);");
withClosurePass = true;
test("var goog, x; goog.exportSymbol('a.b', x);",
"var b, c; b.exportSymbol('a.b', c);");
}
public void testExportToNonStringDoesntExplode() {
withClosurePass = true;
test("var goog, a, b; goog.exportSymbol(a, b);",
"var a, b, c; a.exportSymbol(b, c);");
}
public void testDollarSignSuperExport1() {
useGoogleCodingConvention = false;
// See http://code.google.com/p/closure-compiler/issues/detail?id=32
test("var x = function($super,duper,$fantastic){}",
"var c = function($super, a, b){}");
localRenamingOnly = false;
test("var $super = 1", "var a = 1");
useGoogleCodingConvention = true;
test("var x = function($super,duper,$fantastic){}",
"var c = function($super,a,b){}");
}
public void testDollarSignSuperExport2() {
boolean normalizedExpectedJs = false;
super.enableNormalize(false);
useGoogleCodingConvention = false;
// See http://code.google.com/p/closure-compiler/issues/detail?id=32
test("var x = function($super,duper,$fantastic){};" +
"var y = function($super,duper){};",
"var c = function($super, a, b){};" +
"var d = function($super, a){};");
localRenamingOnly = false;
test("var $super = 1", "var a = 1");
useGoogleCodingConvention = true;
test("var x = function($super,duper,$fantastic){};" +
"var y = function($super,duper){};",
"var c = function($super, a, b ){};" +
"var d = function($super,a){};");
super.disableNormalize();
}
public void testPseudoNames() {
generatePseudoNames = false;
// See http://code.google.com/p/closure-compiler/issues/detail?id=32
test("var foo = function(a, b, c){}",
"var d = function(a, b, c){}");
generatePseudoNames = true;
test("var foo = function(a, b, c){}",
"var $foo$$ = function($a$$, $b$$, $c$$){}");
test("var a = function(a, b, c){}",
"var $a$$ = function($a$$, $b$$, $c$$){}");
}
private void testRenameMapUsingOldMap(String input, String expected,
VariableMap expectedMap) {
previouslyUsedMap = renameVars.getVariableMap();
testRenameMap("", input, expected, expectedMap);
}
private void testRenameMapUsingOldMap(String externs, String input,
String expected,
VariableMap expectedMap) {
previouslyUsedMap = renameVars.getVariableMap();
testRenameMap(externs, input, expected, expectedMap);
}
private void testRenameMap(String input, String expected,
VariableMap expectedRenameMap) {
testRenameMap("", input, expected, expectedRenameMap);
}
private void testRenameMap(String externs, String input, String expected,
VariableMap expectedRenameMap) {
test(externs, input, expected, null, null);
VariableMap renameMap = renameVars.getVariableMap();
assertVariableMapsEqual(expectedRenameMap, renameMap);
}
private VariableMap makeVariableMap(String... keyValPairs) {
Preconditions.checkArgument(keyValPairs.length % 2 == 0);
ImmutableMap.Builder<String, String> renameMap = ImmutableMap.builder();
for (int i = 0; i < keyValPairs.length; i += 2) {
renameMap.put(keyValPairs[i], keyValPairs[i + 1]);
}
return new VariableMap(renameMap.build());
}
private static void assertVariableMapsEqual(VariableMap a, VariableMap b) {
Map<String, String> ma = a.getOriginalNameToNewNameMap();
Map<String, String> mb = b.getOriginalNameToNewNameMap();
assertEquals("VariableMaps not equal", ma, mb);
}
private class ClosurePassAndRenameVars implements CompilerPass {
private final Compiler compiler;
private ClosurePassAndRenameVars(Compiler compiler) {
this.compiler = compiler;
}
@Override
public void process(Node externs, Node root) {
ProcessClosurePrimitives closurePass =
new ProcessClosurePrimitives(
compiler, null, CheckLevel.WARNING);
closurePass.process(externs, root);
renameVars = new RenameVars(compiler, prefix,
false, false, false, false, previouslyUsedMap, null,
closurePass.getExportedVariableNames());
renameVars.process(externs, root);
}
}
}