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/ProcessClosurePrimitivesTest.java

860 lines
29 KiB
Java
Raw Normal View History

2023-04-25 11:33:41 +00:00
/*
* Copyright 2006 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.javascript.rhino.Node;
import com.google.javascript.jscomp.CheckLevel;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.BASE_CLASS_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.DUPLICATE_NAMESPACE_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.EXPECTED_OBJECTLIT_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.FUNCTION_NAMESPACE_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.INVALID_ARGUMENT_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.INVALID_PROVIDE_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.INVALID_STYLE_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.LATE_PROVIDE_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.MISSING_PROVIDE_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.NON_STRING_PASSED_TO_SET_CSS_NAME_MAPPING_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.NULL_ARGUMENT_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.TOO_MANY_ARGUMENTS_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.XMODULE_REQUIRE_ERROR;
import static com.google.javascript.jscomp.ProcessClosurePrimitives.INVALID_CSS_RENAMING_MAP;
/**
* Tests for {@link ProcessClosurePrimitives}.
*
*/
public class ProcessClosurePrimitivesTest extends CompilerTestCase {
private String additionalCode;
private String additionalEndCode;
private boolean addAdditionalNamespace;
public ProcessClosurePrimitivesTest() {
enableLineNumberCheck(true);
}
@Override protected void setUp() {
additionalCode = null;
additionalEndCode = null;
addAdditionalNamespace = false;
}
@Override public CompilerPass getProcessor(final Compiler compiler) {
if ((additionalCode == null) && (additionalEndCode == null)) {
return new ProcessClosurePrimitives(
compiler, null, CheckLevel.ERROR);
} else {
return new CompilerPass() {
@Override
public void process(Node externs, Node root) {
// Process the original code.
new ProcessClosurePrimitives(compiler, null, CheckLevel.OFF)
.process(externs, root);
// Inject additional code at the beginning.
if (additionalCode != null) {
SourceFile file =
SourceFile.fromCode("additionalcode", additionalCode);
Node scriptNode = root.getFirstChild();
Node newScriptNode = new CompilerInput(file).getAstRoot(compiler);
if (addAdditionalNamespace) {
newScriptNode.getFirstChild()
.putBooleanProp(Node.IS_NAMESPACE, true);
}
while (newScriptNode.getLastChild() != null) {
Node lastChild = newScriptNode.getLastChild();
newScriptNode.removeChild(lastChild);
scriptNode.addChildBefore(lastChild, scriptNode.getFirstChild());
}
}
// Inject additional code at the end.
if (additionalEndCode != null) {
SourceFile file =
SourceFile.fromCode("additionalendcode", additionalEndCode);
Node scriptNode = root.getFirstChild();
Node newScriptNode = new CompilerInput(file).getAstRoot(compiler);
if (addAdditionalNamespace) {
newScriptNode.getFirstChild()
.putBooleanProp(Node.IS_NAMESPACE, true);
}
while (newScriptNode.getFirstChild() != null) {
Node firstChild = newScriptNode.getFirstChild();
newScriptNode.removeChild(firstChild);
scriptNode.addChildToBack(firstChild);
}
}
// Process the tree a second time.
new ProcessClosurePrimitives(compiler, null, CheckLevel.ERROR)
.process(externs, root);
}
};
}
}
@Override public int getNumRepetitions() {
return 1;
}
public void testSimpleProvides() {
test("goog.provide('foo');",
"var foo={};");
test("goog.provide('foo.bar');",
"var foo={}; foo.bar={};");
test("goog.provide('foo.bar.baz');",
"var foo={}; foo.bar={}; foo.bar.baz={};");
test("goog.provide('foo.bar.baz.boo');",
"var foo={}; foo.bar={}; foo.bar.baz={}; foo.bar.baz.boo={};");
test("goog.provide('goog.bar');",
"goog.bar={};"); // goog is special-cased
}
public void testMultipleProvides() {
test("goog.provide('foo.bar'); goog.provide('foo.baz');",
"var foo={}; foo.bar={}; foo.baz={};");
test("goog.provide('foo.bar.baz'); goog.provide('foo.boo.foo');",
"var foo={}; foo.bar={}; foo.bar.baz={}; foo.boo={}; foo.boo.foo={};");
test("goog.provide('foo.bar.baz'); goog.provide('foo.bar.boo');",
"var foo={}; foo.bar={}; foo.bar.baz={}; foo.bar.boo={};");
test("goog.provide('foo.bar.baz'); goog.provide('goog.bar.boo');",
"var foo={}; foo.bar={}; foo.bar.baz={}; goog.bar={}; " +
"goog.bar.boo={};");
}
public void testRemovalOfProvidedObjLit() {
test("goog.provide('foo'); foo = 0;",
"var foo = 0;");
test("goog.provide('foo'); foo = {a: 0};",
"var foo = {a: 0};");
test("goog.provide('foo'); foo = function(){};",
"var foo = function(){};");
test("goog.provide('foo'); var foo = 0;",
"var foo = 0;");
test("goog.provide('foo'); var foo = {a: 0};",
"var foo = {a: 0};");
test("goog.provide('foo'); var foo = function(){};",
"var foo = function(){};");
test("goog.provide('foo.bar.Baz'); foo.bar.Baz=function(){};",
"var foo={}; foo.bar={}; foo.bar.Baz=function(){};");
test("goog.provide('foo.bar.moo'); foo.bar.moo={E:1,S:2};",
"var foo={}; foo.bar={}; foo.bar.moo={E:1,S:2};");
test("goog.provide('foo.bar.moo'); foo.bar.moo={E:1}; foo.bar.moo={E:2};",
"var foo={}; foo.bar={}; foo.bar.moo={E:1}; foo.bar.moo={E:2};");
}
public void testProvidedDeclaredFunctionError() {
test("goog.provide('foo'); function foo(){}",
null, FUNCTION_NAMESPACE_ERROR);
}
public void testRemovalMultipleAssignment1() {
test("goog.provide('foo'); foo = 0; foo = 1",
"var foo = 0; foo = 1;");
}
public void testRemovalMultipleAssignment2() {
test("goog.provide('foo'); var foo = 0; foo = 1",
"var foo = 0; foo = 1;");
}
public void testRemovalMultipleAssignment3() {
test("goog.provide('foo'); foo = 0; var foo = 1",
"foo = 0; var foo = 1;");
}
public void testRemovalMultipleAssignment4() {
test("goog.provide('foo.bar'); foo.bar = 0; foo.bar = 1",
"var foo = {}; foo.bar = 0; foo.bar = 1");
}
public void testNoRemovalFunction1() {
test("goog.provide('foo'); function f(){foo = 0}",
"var foo = {}; function f(){foo = 0}");
}
public void testNoRemovalFunction2() {
test("goog.provide('foo'); function f(){var foo = 0}",
"var foo = {}; function f(){var foo = 0}");
}
public void testRemovalMultipleAssignmentInIf1() {
test("goog.provide('foo'); if (true) { var foo = 0 } else { foo = 1 }",
"if (true) { var foo = 0 } else { foo = 1 }");
}
public void testRemovalMultipleAssignmentInIf2() {
test("goog.provide('foo'); if (true) { foo = 0 } else { var foo = 1 }",
"if (true) { foo = 0 } else { var foo = 1 }");
}
public void testRemovalMultipleAssignmentInIf3() {
test("goog.provide('foo'); if (true) { foo = 0 } else { foo = 1 }",
"if (true) { var foo = 0 } else { foo = 1 }");
}
public void testRemovalMultipleAssignmentInIf4() {
test("goog.provide('foo.bar');" +
"if (true) { foo.bar = 0 } else { foo.bar = 1 }",
"var foo = {}; if (true) { foo.bar = 0 } else { foo.bar = 1 }");
}
public void testMultipleDeclarationError1() {
String rest = "if (true) { foo.bar = 0 } else { foo.bar = 1 }";
test("goog.provide('foo.bar');" + "var foo = {};" + rest,
"var foo = {};" + "var foo = {};" + rest);
}
public void testMultipleDeclarationError2() {
test("goog.provide('foo.bar');" +
"if (true) { var foo = {}; foo.bar = 0 } else { foo.bar = 1 }",
"var foo = {};" +
"if (true) {" +
" var foo = {}; foo.bar = 0" +
"} else {" +
" foo.bar = 1" +
"}");
}
public void testMultipleDeclarationError3() {
test("goog.provide('foo.bar');" +
"if (true) { foo.bar = 0 } else { var foo = {}; foo.bar = 1 }",
"var foo = {};" +
"if (true) {" +
" foo.bar = 0" +
"} else {" +
" var foo = {}; foo.bar = 1" +
"}");
}
public void testProvideAfterDeclarationError() {
test("var x = 42; goog.provide('x');",
"var x = 42; var x = {}");
}
public void testProvideErrorCases() {
test("goog.provide();", "", NULL_ARGUMENT_ERROR);
test("goog.provide(5);", "", INVALID_ARGUMENT_ERROR);
test("goog.provide([]);", "", INVALID_ARGUMENT_ERROR);
test("goog.provide({});", "", INVALID_ARGUMENT_ERROR);
test("goog.provide('foo', 'bar');", "", TOO_MANY_ARGUMENTS_ERROR);
test("goog.provide('foo'); goog.provide('foo');", "",
DUPLICATE_NAMESPACE_ERROR);
test("goog.provide('foo.bar'); goog.provide('foo'); goog.provide('foo');",
"", DUPLICATE_NAMESPACE_ERROR);
}
public void testRemovalOfRequires() {
test("goog.provide('foo'); goog.require('foo');",
"var foo={};");
test("goog.provide('foo.bar'); goog.require('foo.bar');",
"var foo={}; foo.bar={};");
test("goog.provide('foo.bar.baz'); goog.require('foo.bar.baz');",
"var foo={}; foo.bar={}; foo.bar.baz={};");
test("goog.provide('foo'); var x = 3; goog.require('foo'); something();",
"var foo={}; var x = 3; something();");
testSame("foo.require('foo.bar');");
}
public void testRequireErrorCases() {
test("goog.require();", "", NULL_ARGUMENT_ERROR);
test("goog.require(5);", "", INVALID_ARGUMENT_ERROR);
test("goog.require([]);", "", INVALID_ARGUMENT_ERROR);
test("goog.require({});", "", INVALID_ARGUMENT_ERROR);
}
public void testLateProvides() {
test("goog.require('foo'); goog.provide('foo');",
"var foo={};", LATE_PROVIDE_ERROR);
test("goog.require('foo.bar'); goog.provide('foo.bar');",
"var foo={}; foo.bar={};", LATE_PROVIDE_ERROR);
test("goog.provide('foo.bar'); goog.require('foo'); goog.provide('foo');",
"var foo={}; foo.bar={};", LATE_PROVIDE_ERROR);
}
public void testMissingProvides() {
test("goog.require('foo');",
"", MISSING_PROVIDE_ERROR);
test("goog.provide('foo'); goog.require('Foo');",
"var foo={};", MISSING_PROVIDE_ERROR);
test("goog.provide('foo'); goog.require('foo.bar');",
"var foo={};", MISSING_PROVIDE_ERROR);
test("goog.provide('foo'); var EXPERIMENT_FOO = true; " +
"if (EXPERIMENT_FOO) {goog.require('foo.bar');}",
"var foo={}; var EXPERIMENT_FOO = true; if (EXPERIMENT_FOO) {}",
MISSING_PROVIDE_ERROR);
}
public void testAddDependency() {
test("goog.addDependency('x.js', ['A', 'B'], []);", "0");
Compiler compiler = getLastCompiler();
assertTrue(compiler.getTypeRegistry().isForwardDeclaredType("A"));
assertTrue(compiler.getTypeRegistry().isForwardDeclaredType("B"));
assertFalse(compiler.getTypeRegistry().isForwardDeclaredType("C"));
}
public void testValidSetCssNameMapping() {
test("goog.setCssNameMapping({foo:'bar',\"biz\":'baz'});", "");
CssRenamingMap map = getLastCompiler().getCssRenamingMap();
assertNotNull(map);
assertEquals("bar", map.get("foo"));
assertEquals("baz", map.get("biz"));
}
public void testValidSetCssNameMappingWithType() {
test("goog.setCssNameMapping({foo:'bar',\"biz\":'baz'}, 'BY_PART');", "");
CssRenamingMap map = getLastCompiler().getCssRenamingMap();
assertNotNull(map);
assertEquals("bar", map.get("foo"));
assertEquals("baz", map.get("biz"));
test("goog.setCssNameMapping({foo:'bar',biz:'baz','biz-foo':'baz-bar'}," +
" 'BY_WHOLE');", "");
map = getLastCompiler().getCssRenamingMap();
assertNotNull(map);
assertEquals("bar", map.get("foo"));
assertEquals("baz", map.get("biz"));
assertEquals("baz-bar", map.get("biz-foo"));
}
public void testSetCssNameMappingNonStringValueReturnsError() {
// Make sure the argument is an object literal.
test("var BAR = {foo:'bar'}; goog.setCssNameMapping(BAR);", "",
EXPECTED_OBJECTLIT_ERROR);
test("goog.setCssNameMapping([]);", "",
EXPECTED_OBJECTLIT_ERROR);
test("goog.setCssNameMapping(false);", "",
EXPECTED_OBJECTLIT_ERROR);
test("goog.setCssNameMapping(null);", "",
EXPECTED_OBJECTLIT_ERROR);
test("goog.setCssNameMapping(undefined);", "",
EXPECTED_OBJECTLIT_ERROR);
// Make sure all values of the object literal are string literals.
test("var BAR = 'bar'; goog.setCssNameMapping({foo:BAR});", "",
NON_STRING_PASSED_TO_SET_CSS_NAME_MAPPING_ERROR);
test("goog.setCssNameMapping({foo:6});", "",
NON_STRING_PASSED_TO_SET_CSS_NAME_MAPPING_ERROR);
test("goog.setCssNameMapping({foo:false});", "",
NON_STRING_PASSED_TO_SET_CSS_NAME_MAPPING_ERROR);
test("goog.setCssNameMapping({foo:null});", "",
NON_STRING_PASSED_TO_SET_CSS_NAME_MAPPING_ERROR);
test("goog.setCssNameMapping({foo:undefined});", "",
NON_STRING_PASSED_TO_SET_CSS_NAME_MAPPING_ERROR);
}
public void testSetCssNameMappingValidity() {
// Make sure that the keys don't have -'s
test("goog.setCssNameMapping({'a': 'b', 'a-a': 'c'})", "", null,
INVALID_CSS_RENAMING_MAP);
// In full mode, we check that map(a-b)=map(a)-map(b)
test("goog.setCssNameMapping({'a': 'b', 'a-a': 'c'}, 'BY_WHOLE')", "", null,
INVALID_CSS_RENAMING_MAP);
// Unknown mapping type
test("goog.setCssNameMapping({foo:'bar'}, 'UNKNOWN');", "",
INVALID_STYLE_ERROR);
}
public void testBadCrossModuleRequire() {
test(
createModuleStar(
"",
"goog.provide('goog.ui');",
"goog.require('goog.ui');"),
new String[] {
"",
"goog.ui = {};",
""
},
null,
XMODULE_REQUIRE_ERROR);
}
public void testGoodCrossModuleRequire1() {
test(
createModuleStar(
"goog.provide('goog.ui');",
"",
"goog.require('goog.ui');"),
new String[] {
"goog.ui = {};",
"",
"",
});
}
public void testGoodCrossModuleRequire2() {
test(
createModuleStar(
"",
"",
"goog.provide('goog.ui'); goog.require('goog.ui');"),
new String[] {
"",
"",
"goog.ui = {};",
});
}
// Tests providing additional code with non-overlapping var namespace.
public void testSimpleAdditionalProvide() {
additionalCode = "goog.provide('b.B'); b.B = {};";
test("goog.provide('a.A'); a.A = {};",
"var b={};b.B={};var a={};a.A={};");
}
// Same as above, but with the additional code added after the original.
public void testSimpleAdditionalProvideAtEnd() {
additionalEndCode = "goog.provide('b.B'); b.B = {};";
test("goog.provide('a.A'); a.A = {};",
"var a={};a.A={};var b={};b.B={};");
}
// Tests providing additional code with non-overlapping dotted namespace.
public void testSimpleDottedAdditionalProvide() {
additionalCode = "goog.provide('a.b.B'); a.b.B = {};";
test("goog.provide('c.d.D'); c.d.D = {};",
"var a={};a.b={};a.b.B={};var c={};c.d={};c.d.D={};");
}
// Tests providing additional code with overlapping var namespace.
public void testOverlappingAdditionalProvide() {
additionalCode = "goog.provide('a.B'); a.B = {};";
test("goog.provide('a.A'); a.A = {};",
"var a={};a.B={};a.A={};");
}
// Tests providing additional code with overlapping var namespace.
public void testOverlappingAdditionalProvideAtEnd() {
additionalEndCode = "goog.provide('a.B'); a.B = {};";
test("goog.provide('a.A'); a.A = {};",
"var a={};a.A={};a.B={};");
}
// Tests providing additional code with overlapping dotted namespace.
public void testOverlappingDottedAdditionalProvide() {
additionalCode = "goog.provide('a.b.B'); a.b.B = {};";
test("goog.provide('a.b.C'); a.b.C = {};",
"var a={};a.b={};a.b.B={};a.b.C={};");
}
// Tests that a require of additional code generates no error.
public void testRequireOfAdditionalProvide() {
additionalCode = "goog.provide('b.B'); b.B = {};";
test("goog.require('b.B'); goog.provide('a.A'); a.A = {};",
"var b={};b.B={};var a={};a.A={};");
}
// Tests that a require not in additional code generates (only) one error.
public void testMissingRequireWithAdditionalProvide() {
additionalCode = "goog.provide('b.B'); b.B = {};";
test("goog.require('b.C'); goog.provide('a.A'); a.A = {};",
"var b={};b.B={};var a={};a.A={};",
MISSING_PROVIDE_ERROR);
}
// Tests that a require in additional code generates no error.
public void testLateRequire() {
additionalEndCode = "goog.require('a.A');";
test("goog.provide('a.A'); a.A = {};",
"var a={};a.A={};");
}
// Tests a case where code is reordered after processing provides and then
// provides are processed again.
public void testReorderedProvides() {
additionalCode = "a.B = {};"; // as if a.B was after a.A originally
addAdditionalNamespace = true;
test("goog.provide('a.A'); a.A = {};",
"var a={};a.B={};a.A={};");
}
// Another version of above.
public void testReorderedProvides2() {
additionalEndCode = "a.B = {};";
addAdditionalNamespace = true;
test("goog.provide('a.A'); a.A = {};",
"var a={};a.A={};a.B={};");
}
// Provide a name before the definition of the class providing the
// parent namespace.
public void testProvideOrder1() {
additionalEndCode = "";
addAdditionalNamespace = false;
// TODO(johnlenz): This test confirms that the constructor (a.b) isn't
// improperly removed, but this result isn't really what we want as the
// reassign of a.b removes the definition of "a.b.c".
test("goog.provide('a.b');" +
"goog.provide('a.b.c');" +
"a.b.c;" +
"a.b = function(x,y) {};",
"var a = {};" +
"a.b = {};" +
"a.b.c = {};" +
"a.b.c;" +
"a.b = function(x,y) {};");
}
// Provide a name after the definition of the class providing the
// parent namespace.
public void testProvideOrder2() {
additionalEndCode = "";
addAdditionalNamespace = false;
// TODO(johnlenz): This test confirms that the constructor (a.b) isn't
// improperly removed, but this result isn't really what we want as
// namespace placeholders for a.b and a.b.c remain.
test("goog.provide('a.b');" +
"goog.provide('a.b.c');" +
"a.b = function(x,y) {};" +
"a.b.c;",
"var a = {};" +
"a.b = {};" +
"a.b.c = {};" +
"a.b = function(x,y) {};" +
"a.b.c;");
}
// Provide a name after the definition of the class providing the
// parent namespace.
public void testProvideOrder3a() {
test("goog.provide('a.b');" +
"a.b = function(x,y) {};" +
"goog.provide('a.b.c');" +
"a.b.c;",
"var a = {};" +
"a.b = function(x,y) {};" +
"a.b.c = {};" +
"a.b.c;");
}
public void testProvideOrder3b() {
additionalEndCode = "";
addAdditionalNamespace = false;
// This tests a cleanly provided name, below a function namespace.
test("goog.provide('a.b');" +
"a.b = function(x,y) {};" +
"goog.provide('a.b.c');" +
"a.b.c;",
"var a = {};" +
"a.b = function(x,y) {};" +
"a.b.c = {};" +
"a.b.c;");
}
public void testProvideOrder4a() {
test("goog.provide('goog.a');" +
"goog.provide('goog.a.b');" +
"if (x) {" +
" goog.a.b = 1;" +
"} else {" +
" goog.a.b = 2;" +
"}",
"goog.a={};" +
"if(x)" +
" goog.a.b=1;" +
"else" +
" goog.a.b=2;");
}
public void testProvideOrder4b() {
additionalEndCode = "";
addAdditionalNamespace = false;
// This tests a cleanly provided name, below a namespace.
test("goog.provide('goog.a');" +
"goog.provide('goog.a.b');" +
"if (x) {" +
" goog.a.b = 1;" +
"} else {" +
" goog.a.b = 2;" +
"}",
"goog.a={};" +
"if(x)" +
" goog.a.b=1;" +
"else" +
" goog.a.b=2;");
}
public void testInvalidProvide() {
test("goog.provide('a.class');", null, INVALID_PROVIDE_ERROR);
}
private static final String METHOD_FORMAT =
"function Foo() {} Foo.prototype.method = function() { %s };";
private static final String FOO_INHERITS =
"goog.inherits(Foo, BaseFoo);";
public void testInvalidBase1() {
test("goog.base(this, 'method');", null, BASE_CLASS_ERROR);
}
public void testInvalidBase2() {
test("function Foo() {}" +
"Foo.method = function() {" +
" goog.base(this, 'method');" +
"};", null, BASE_CLASS_ERROR);
}
public void testInvalidBase3() {
test(String.format(METHOD_FORMAT, "goog.base();"),
null, BASE_CLASS_ERROR);
}
public void testInvalidBase4() {
test(String.format(METHOD_FORMAT, "goog.base(this, 'bar');"),
null, BASE_CLASS_ERROR);
}
public void testInvalidBase5() {
test(String.format(METHOD_FORMAT, "goog.base('foo', 'method');"),
null, BASE_CLASS_ERROR);
}
public void testInvalidBase6() {
test(String.format(METHOD_FORMAT, "goog.base.call(null, this, 'method');"),
null, BASE_CLASS_ERROR);
}
public void testInvalidBase7() {
test("function Foo() { goog.base(this); }",
null, BASE_CLASS_ERROR);
}
public void testInvalidBase8() {
test("var Foo = function() { goog.base(this); }",
null, BASE_CLASS_ERROR);
}
public void testInvalidBase9() {
test("var goog = {}; goog.Foo = function() { goog.base(this); }",
null, BASE_CLASS_ERROR);
}
public void testValidBase1() {
test(String.format(METHOD_FORMAT, "goog.base(this, 'method');"),
String.format(METHOD_FORMAT, "Foo.superClass_.method.call(this)"));
}
public void testValidBase2() {
test(String.format(METHOD_FORMAT, "goog.base(this, 'method', 1, 2);"),
String.format(METHOD_FORMAT,
"Foo.superClass_.method.call(this, 1, 2)"));
}
public void testValidBase3() {
test(String.format(METHOD_FORMAT, "return goog.base(this, 'method');"),
String.format(METHOD_FORMAT,
"return Foo.superClass_.method.call(this)"));
}
public void testValidBase4() {
test("function Foo() { goog.base(this, 1, 2); }" + FOO_INHERITS,
"function Foo() { BaseFoo.call(this, 1, 2); } " + FOO_INHERITS);
}
public void testValidBase5() {
test("var Foo = function() { goog.base(this, 1); };" + FOO_INHERITS,
"var Foo = function() { BaseFoo.call(this, 1); }; " + FOO_INHERITS);
}
public void testValidBase6() {
test("var goog = {}; goog.Foo = function() { goog.base(this); }; " +
"goog.inherits(goog.Foo, goog.BaseFoo);",
"var goog = {}; goog.Foo = function() { goog.BaseFoo.call(this); }; " +
"goog.inherits(goog.Foo, goog.BaseFoo);");
}
public void testImplicitAndExplicitProvide() {
test("var goog = {}; " +
"goog.provide('goog.foo.bar'); goog.provide('goog.foo');",
"var goog = {}; goog.foo = {}; goog.foo.bar = {};");
}
public void testImplicitProvideInIndependentModules() {
test(
createModuleStar(
"",
"goog.provide('apps.A');",
"goog.provide('apps.B');"),
new String[] {
"var apps = {};",
"apps.A = {};",
"apps.B = {};",
});
}
public void testImplicitProvideInIndependentModules2() {
test(
createModuleStar(
"goog.provide('apps');",
"goog.provide('apps.foo.A');",
"goog.provide('apps.foo.B');"),
new String[] {
"var apps = {}; apps.foo = {};",
"apps.foo.A = {};",
"apps.foo.B = {};",
});
}
public void testImplicitProvideInIndependentModules3() {
test(
createModuleStar(
"var goog = {};",
"goog.provide('goog.foo.A');",
"goog.provide('goog.foo.B');"),
new String[] {
"var goog = {}; goog.foo = {};",
"goog.foo.A = {};",
"goog.foo.B = {};",
});
}
public void testProvideInIndependentModules1() {
test(
createModuleStar(
"goog.provide('apps');",
"goog.provide('apps.foo');",
"goog.provide('apps.foo.B');"),
new String[] {
"var apps = {}; apps.foo = {};",
"",
"apps.foo.B = {};",
});
}
public void testProvideInIndependentModules2() {
// TODO(nicksantos): Make this an error.
test(
createModuleStar(
"goog.provide('apps');",
"goog.provide('apps.foo'); apps.foo = {};",
"goog.provide('apps.foo.B');"),
new String[] {
"var apps = {};",
"apps.foo = {};",
"apps.foo.B = {};",
});
}
public void testProvideInIndependentModules2b() {
// TODO(nicksantos): Make this an error.
test(
createModuleStar(
"goog.provide('apps');",
"goog.provide('apps.foo'); apps.foo = function() {};",
"goog.provide('apps.foo.B');"),
new String[] {
"var apps = {};",
"apps.foo = function() {};",
"apps.foo.B = {};",
});
}
public void testProvideInIndependentModules3() {
test(
createModuleStar(
"goog.provide('apps');",
"goog.provide('apps.foo.B');",
"goog.provide('apps.foo'); goog.require('apps.foo');"),
new String[] {
"var apps = {}; apps.foo = {};",
"apps.foo.B = {};",
"",
});
}
public void testProvideInIndependentModules3b() {
// TODO(nicksantos): Make this an error.
test(
createModuleStar(
"goog.provide('apps');",
"goog.provide('apps.foo.B');",
"goog.provide('apps.foo'); apps.foo = function() {}; " +
"goog.require('apps.foo');"),
new String[] {
"var apps = {};",
"apps.foo.B = {};",
"apps.foo = function() {};",
});
}
public void testProvideInIndependentModules4() {
// Regression test for bug 261:
// http://code.google.com/p/closure-compiler/issues/detail?id=261
test(
createModuleStar(
"goog.provide('apps');",
"goog.provide('apps.foo.bar.B');",
"goog.provide('apps.foo.bar.C');"),
new String[] {
"var apps = {};apps.foo = {};apps.foo.bar = {}",
"apps.foo.bar.B = {};",
"apps.foo.bar.C = {};",
});
}
public void testRequireOfBaseGoog() {
test("goog.require('goog');",
"", MISSING_PROVIDE_ERROR);
}
public void testSourcePositionPreservation() {
test("goog.provide('foo.bar.baz');",
"var foo = {};" +
"foo.bar = {};" +
"foo.bar.baz = {};");
Node root = getLastCompiler().getRoot();
Node fooDecl = findQualifiedNameNode("foo", root);
Node fooBarDecl = findQualifiedNameNode("foo.bar", root);
Node fooBarBazDecl = findQualifiedNameNode("foo.bar.baz", root);
assertEquals(1, fooDecl.getLineno());
assertEquals(14, fooDecl.getCharno());
assertEquals(1, fooBarDecl.getLineno());
assertEquals(18, fooBarDecl.getCharno());
assertEquals(1, fooBarBazDecl.getLineno());
assertEquals(22, fooBarBazDecl.getCharno());
}
public void testNoStubForProvidedTypedef() {
test("goog.provide('x'); /** @typedef {number} */ var x;", "var x;");
}
public void testNoStubForProvidedTypedef2() {
test("goog.provide('x.y'); /** @typedef {number} */ x.y;",
"var x = {}; x.y;");
}
public void testNoStubForProvidedTypedef4() {
test("goog.provide('x.y.z'); /** @typedef {number} */ x.y.z;",
"var x = {}; x.y = {}; x.y.z;");
}
public void testProvideRequireSameFile() {
test("goog.provide('x');\ngoog.require('x');", "var x = {};");
}
}