126 lines
4.3 KiB
Java
126 lines
4.3 KiB
Java
|
/*
|
||
|
* 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.jscomp.CheckLevel;
|
||
|
|
||
|
public class CheckSideEffectsTest extends CompilerTestCase {
|
||
|
public CheckSideEffectsTest() {
|
||
|
this.parseTypeInfo = true;
|
||
|
allowExternsChanges(true);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected int getNumRepetitions() {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected CompilerPass getProcessor(Compiler compiler) {
|
||
|
return new CheckSideEffects(compiler, CheckLevel.WARNING, true);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void test(String js, String expected, DiagnosticType warning) {
|
||
|
test(js, expected, null, warning);
|
||
|
}
|
||
|
|
||
|
public void test(String js, DiagnosticType warning) {
|
||
|
test(js, js, null, warning);
|
||
|
}
|
||
|
|
||
|
final DiagnosticType e = CheckSideEffects.USELESS_CODE_ERROR;
|
||
|
final DiagnosticType ok = null; // no warning
|
||
|
|
||
|
public void testUselessCode() {
|
||
|
test("function f(x) { if(x) return; }", ok);
|
||
|
test("function f(x) { if(x); }", "function f(x) { if(x); }", e);
|
||
|
|
||
|
test("if(x) x = y;", ok);
|
||
|
test("if(x) x == bar();", "if(x) JSCOMPILER_PRESERVE(x == bar());", e);
|
||
|
|
||
|
test("x = 3;", ok);
|
||
|
test("x == 3;", "JSCOMPILER_PRESERVE(x == 3);", e);
|
||
|
|
||
|
test("var x = 'test'", ok);
|
||
|
test("var x = 'test'\n'str'",
|
||
|
"var x = 'test'\nJSCOMPILER_PRESERVE('str')", e);
|
||
|
|
||
|
test("", ok);
|
||
|
test("foo();;;;bar();;;;", ok);
|
||
|
|
||
|
test("var a, b; a = 5, b = 6", ok);
|
||
|
test("var a, b; a = 5, b == 6",
|
||
|
"var a, b; a = 5, JSCOMPILER_PRESERVE(b == 6)", e);
|
||
|
test("var a, b; a = (5, 6)",
|
||
|
"var a, b; a = (JSCOMPILER_PRESERVE(5), 6)", e);
|
||
|
test("var a, b; a = (bar(), 6, 7)",
|
||
|
"var a, b; a = (bar(), JSCOMPILER_PRESERVE(6), 7)", e);
|
||
|
test("var a, b; a = (bar(), bar(), 7, 8)",
|
||
|
"var a, b; a = (bar(), bar(), JSCOMPILER_PRESERVE(7), 8)", e);
|
||
|
test("var a, b; a = (b = 7, 6)", ok);
|
||
|
test("function x(){}\nfunction f(a, b){}\nf(1,(x(), 2));", ok);
|
||
|
test("function x(){}\nfunction f(a, b){}\nf(1,(2, 3));",
|
||
|
"function x(){}\nfunction f(a, b){}\n" +
|
||
|
"f(1,(JSCOMPILER_PRESERVE(2), 3));", e);
|
||
|
}
|
||
|
|
||
|
public void testUselessCodeInFor() {
|
||
|
test("for(var x = 0; x < 100; x++) { foo(x) }", ok);
|
||
|
test("for(; true; ) { bar() }", ok);
|
||
|
test("for(foo(); true; foo()) { bar() }", ok);
|
||
|
test("for(void 0; true; foo()) { bar() }",
|
||
|
"for(JSCOMPILER_PRESERVE(void 0); true; foo()) { bar() }", e);
|
||
|
test("for(foo(); true; void 0) { bar() }",
|
||
|
"for(foo(); true; JSCOMPILER_PRESERVE(void 0)) { bar() }", e);
|
||
|
test("for(foo(); true; (1, bar())) { bar() }",
|
||
|
"for(foo(); true; (JSCOMPILER_PRESERVE(1), bar())) { bar() }", e);
|
||
|
|
||
|
test("for(foo in bar) { foo() }", ok);
|
||
|
test("for (i = 0; el = el.previousSibling; i++) {}", ok);
|
||
|
test("for (i = 0; el = el.previousSibling; i++);", ok);
|
||
|
}
|
||
|
|
||
|
public void testTypeAnnotations() {
|
||
|
test("x;", "JSCOMPILER_PRESERVE(x);", e);
|
||
|
test("a.b.c.d;", "JSCOMPILER_PRESERVE(a.b.c.d);", e);
|
||
|
test("/** @type Number */ a.b.c.d;", ok);
|
||
|
test("if (true) { /** @type Number */ a.b.c.d; }", ok);
|
||
|
|
||
|
test("function A() { this.foo; }",
|
||
|
"function A() { JSCOMPILER_PRESERVE(this.foo); }", e);
|
||
|
test("function A() { /** @type Number */ this.foo; }", ok);
|
||
|
}
|
||
|
|
||
|
public void testJSDocComments() {
|
||
|
test("function A() { /** This is a JsDoc comment */ this.foo; }", ok);
|
||
|
test("function A() { /* This is a normal comment */ this.foo; }",
|
||
|
"function A() { " +
|
||
|
" /* This is a normal comment */ JSCOMPILER_PRESERVE(this.foo); }", e);
|
||
|
}
|
||
|
|
||
|
public void testIssue80() {
|
||
|
test("(0, eval)('alert');", ok);
|
||
|
test("(0, foo)('alert');", "(JSCOMPILER_PRESERVE(0), foo)('alert');", e);
|
||
|
}
|
||
|
|
||
|
public void testIsue504() {
|
||
|
test("void f();", "JSCOMPILER_PRESERVE(void f());", null, e,
|
||
|
"Suspicious code. The result of the 'void' operator is not being used.");
|
||
|
}
|
||
|
}
|