/*
* Copyright 2016 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 static com.google.javascript.jscomp.Es6ToEs3Converter.CANNOT_CONVERT;
import com.google.common.collect.ImmutableList;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
public final class Es6ExtractClassesTest extends CompilerTestCase {
@Override
protected CompilerPass getProcessor(Compiler compiler) {
return new Es6ExtractClasses(compiler);
}
@Override
protected void setUp() {
setAcceptedLanguage(LanguageMode.ECMASCRIPT_2015);
setLanguageOut(LanguageMode.ECMASCRIPT3);
disableTypeCheck();
runTypeCheckAfterProcessing = true;
}
public void testExtractionFromCall() {
test(
"f(class{});",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {};",
"f(testcode$classdecl$var0);"));
}
public void testSelfReference1() {
test(
"var Outer = class Inner { constructor() { alert(Inner); } };",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {",
" constructor() { alert(testcode$classdecl$var0); }",
"};",
"var Outer=testcode$classdecl$var0"));
test(
"let Outer = class Inner { constructor() { alert(Inner); } };",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {",
" constructor() { alert(testcode$classdecl$var0); }",
"};",
"let Outer=testcode$classdecl$var0"));
test(
"const Outer = class Inner { constructor() { alert(Inner); } };",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {",
" constructor() { alert(testcode$classdecl$var0); }",
"};",
"const Outer=testcode$classdecl$var0"));
}
public void testSelfReference2() {
test(
"alert(class C { constructor() { alert(C); } });",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {",
" constructor() { alert(testcode$classdecl$var0); }",
"};",
"alert(testcode$classdecl$var0)"));
}
public void testSelfReference3() {
test(
LINE_JOINER.join(
"alert(class C {",
" m1() { class C {}; alert(C); }",
" m2() { alert(C); }",
"});"),
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {",
" m1() { class C {}; alert(C); }",
" m2() { alert(testcode$classdecl$var0); }",
"};",
"alert(testcode$classdecl$var0)"));
}
public void testSelfReference_googModule() {
test(
LINE_JOINER.join(
"goog.module('example');",
"exports = class Inner { constructor() { alert(Inner); } };"),
LINE_JOINER.join(
"goog.module('example');",
"const testcode$classdecl$var0 = class {",
" constructor() {",
" alert(testcode$classdecl$var0);",
" }",
"};",
"exports = testcode$classdecl$var0;"));
}
public void testSelfReference_qualifiedName() {
test(
"outer.qual.Name = class Inner { constructor() { alert(Inner); } };",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {",
" constructor() {",
" alert(testcode$classdecl$var0);",
" }",
"};",
"outer.qual.Name = testcode$classdecl$var0;"));
}
public void testConstAssignment() {
test(
"var foo = bar(class {});",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {};",
"var foo = bar(testcode$classdecl$var0);"));
}
public void testLetAssignment() {
test(
"let foo = bar(class {});",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {};",
"let foo = bar(testcode$classdecl$var0);"));
}
public void testVarAssignment() {
test(
"var foo = bar(class {});",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {};",
"var foo = bar(testcode$classdecl$var0);"));
}
public void testJSDoc() {
test(
"/** @unrestricted */ var foo = class bar {};",
LINE_JOINER.join(
"/** @unrestricted */",
"const testcode$classdecl$var0 = class {};",
"/** @unrestricted */",
"var foo = testcode$classdecl$var0;"));
}
public void testFilenameContainsAt() {
test(
ImmutableList.of(
SourceFile.fromCode("unusual@name", "alert(class {});")),
ImmutableList.of(
SourceFile.fromCode(
"unusual@name",
LINE_JOINER.join(
"const unusual$name$classdecl$var0 = class{};",
"alert(unusual$name$classdecl$var0);"))));
}
public void testFilenameContainsPlus() {
test(
ImmutableList.of(
SourceFile.fromCode("+some/+path/file", "alert(class {});")),
ImmutableList.of(
SourceFile.fromCode(
"+path/file",
LINE_JOINER.join(
"const $some$$path$file$classdecl$var0 = class{};",
"alert($some$$path$file$classdecl$var0);"))));
}
public void testConditionalBlocksExtractionFromCall() {
testError("maybeTrue() && f(class{});", CANNOT_CONVERT);
}
public void testExtractionFromArrayLiteral() {
test(
"var c = [class C {}];",
LINE_JOINER.join(
"const testcode$classdecl$var0 = class {};",
"var c = [testcode$classdecl$var0];"));
}
public void testTernaryOperatorBlocksExtraction() {
testError("var c = maybeTrue() ? class A {} : anotherExpr", CANNOT_CONVERT);
testError("var c = maybeTrue() ? anotherExpr : class B {}", CANNOT_CONVERT);
}
public void testCannotExtract() {
testError(
"var c = maybeTrue() && class A extends sideEffect() {}",
CANNOT_CONVERT);
testError(
LINE_JOINER.join(
"var x;",
"function f(x, y) {}",
"f(x = 2, class Foo { [x=3]() {} });"),
CANNOT_CONVERT);
}
public void testClassesHandledByEs6ToEs3Converter() {
testSame("class C{}");
testSame("var c = class {};");
}
}