218 lines
6.3 KiB
Java
218 lines
6.3 KiB
Java
|
/*
|
||
|
* Copyright 2008 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;
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Test that warnings are generated in appropriate cases and appropriate
|
||
|
* cases only by VariableReferenceCheck
|
||
|
*
|
||
|
*/
|
||
|
public class VariableReferenceCheckTest extends CompilerTestCase {
|
||
|
|
||
|
private static final String VARIABLE_RUN =
|
||
|
"var a = 1; var b = 2; var c = a + b, d = c;";
|
||
|
|
||
|
private boolean enableAmbiguousFunctionCheck = false;
|
||
|
|
||
|
@Override
|
||
|
public CompilerOptions getOptions() {
|
||
|
CompilerOptions options = super.getOptions();
|
||
|
if (enableAmbiguousFunctionCheck) {
|
||
|
options.setWarningLevel(
|
||
|
DiagnosticGroups.AMBIGUOUS_FUNCTION_DECL, CheckLevel.WARNING);
|
||
|
}
|
||
|
return options;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public CompilerPass getProcessor(Compiler compiler) {
|
||
|
// Treats bad reads as errors, and reports bad write warnings.
|
||
|
return new VariableReferenceCheck(compiler, CheckLevel.WARNING);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void setUp() throws Exception {
|
||
|
super.setUp();
|
||
|
enableAmbiguousFunctionCheck = false;
|
||
|
}
|
||
|
|
||
|
public void testCorrectCode() {
|
||
|
assertNoWarning("function foo(d) { (function() { d.foo(); }); d.bar(); } ");
|
||
|
assertNoWarning("function foo() { bar(); } function bar() { foo(); } ");
|
||
|
assertNoWarning("function f(d) { d = 3; }");
|
||
|
assertNoWarning(VARIABLE_RUN);
|
||
|
assertNoWarning("function f() { " + VARIABLE_RUN + "}");
|
||
|
}
|
||
|
|
||
|
public void testCorrectShadowing() {
|
||
|
assertNoWarning(VARIABLE_RUN + "function f() { " + VARIABLE_RUN + "}");
|
||
|
}
|
||
|
|
||
|
public void testCorrectRedeclare() {
|
||
|
assertNoWarning(
|
||
|
"function f() { if (1) { var a = 2; } else { var a = 3; } }");
|
||
|
}
|
||
|
|
||
|
public void testCorrectRecursion() {
|
||
|
assertNoWarning("function f() { var x = function() { x(); }; }");
|
||
|
}
|
||
|
|
||
|
public void testCorrectCatch() {
|
||
|
assertNoWarning("function f() { try { var x = 2; } catch (x) {} }");
|
||
|
}
|
||
|
|
||
|
public void testRedeclare() {
|
||
|
// Only test local scope since global scope is covered elsewhere
|
||
|
assertRedeclare("function f() { var a = 2; var a = 3; }");
|
||
|
assertRedeclare("function f(a) { var a = 2; }");
|
||
|
}
|
||
|
|
||
|
public void testEarlyReference() {
|
||
|
assertUndeclared("function f() { a = 2; var a = 3; }");
|
||
|
}
|
||
|
|
||
|
public void testCorrectEarlyReference() {
|
||
|
assertNoWarning("var goog = goog || {}");
|
||
|
assertNoWarning("function f() { a = 2; } var a = 2;");
|
||
|
}
|
||
|
|
||
|
public void testUnreferencedBleedingFunction() {
|
||
|
assertNoWarning("var x = function y() {}");
|
||
|
}
|
||
|
|
||
|
public void testReferencedBleedingFunction() {
|
||
|
assertNoWarning("var x = function y() { return y(); }");
|
||
|
}
|
||
|
|
||
|
public void testDoubleDeclaration() {
|
||
|
assertRedeclare("function x(y) { if (true) { var y; } }");
|
||
|
}
|
||
|
|
||
|
public void testDoubleDeclaration2() {
|
||
|
assertRedeclare("function x() { var y; if (true) { var y; } }");
|
||
|
}
|
||
|
|
||
|
public void testHoistedFunction1() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertNoWarning("f(); function f() {}");
|
||
|
}
|
||
|
|
||
|
public void testHoistedFunction2() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertNoWarning("function g() { f(); function f() {} }");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedFunction() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertUndeclared("if (true) { f(); function f() {} }");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedFunction2() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertNoWarning("if (false) { function f() {} f(); }");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedFunction3() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertNoWarning("function g() { if (false) { function f() {} f(); }}");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedFunction4() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertAmbiguous("if (false) { function f() {} } f();");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedFunction5() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertAmbiguous("function g() { if (false) { function f() {} } f(); }");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedFunction6() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertUndeclared("if (false) { f(); function f() {} }");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedFunction7() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertUndeclared("function g() { if (false) { f(); function f() {} }}");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedRecursiveFunction1() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertNoWarning("if (false) { function f() { f(); }}");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedRecursiveFunction2() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertNoWarning("function g() { if (false) { function f() { f(); }}}");
|
||
|
}
|
||
|
|
||
|
public void testNonHoistedRecursiveFunction3() {
|
||
|
enableAmbiguousFunctionCheck = true;
|
||
|
assertNoWarning("function g() { if (false) { function f() { f(); g(); }}}");
|
||
|
}
|
||
|
|
||
|
public void testNoWarnInExterns1() {
|
||
|
// Verify duplicate suppressions are properly recognized.
|
||
|
String externs =
|
||
|
"var google;" +
|
||
|
"/** @suppress {duplicate} */ var google";
|
||
|
String code = "";
|
||
|
test(externs, code, code, null, null);
|
||
|
}
|
||
|
|
||
|
public void testNoWarnInExterns2() {
|
||
|
// Verify we don't complain about early references in externs
|
||
|
String externs =
|
||
|
"window;" +
|
||
|
"var window;";
|
||
|
String code = "";
|
||
|
test(externs, code, code, null, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Expects the JS to generate one bad-read error.
|
||
|
*/
|
||
|
private void assertRedeclare(String js) {
|
||
|
testSame(js, VariableReferenceCheck.REDECLARED_VARIABLE);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Expects the JS to generate one bad-write warning.
|
||
|
*/
|
||
|
private void assertUndeclared(String js) {
|
||
|
testSame(js, VariableReferenceCheck.UNDECLARED_REFERENCE);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Expects the JS to generate one bad-write warning.
|
||
|
*/
|
||
|
private void assertAmbiguous(String js) {
|
||
|
testSame(js, VariableReferenceCheck.AMBIGUOUS_FUNCTION_DECL);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Expects the JS to generate no errors or warnings.
|
||
|
*/
|
||
|
private void assertNoWarning(String js) {
|
||
|
testSame(js);
|
||
|
}
|
||
|
}
|