/* * Copyright 2015 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.common.truth.Truth.THROW_ASSERTION_ERROR; import static com.google.common.truth.Truth.assertThat; import static java.util.Arrays.asList; import com.google.common.truth.FailureStrategy; import com.google.common.truth.Subject; import com.google.javascript.jscomp.CompilerOptions.LanguageMode; import com.google.javascript.jscomp.testing.TestErrorManager; import com.google.javascript.rhino.Node; /** * This test is temporary. It asserts that the CodeGenerator produces the * right ES6_TYPED sources, even though those sources don't yet parse. * All these test cases should be migrated to a round-trip test as the parser * catches up. * * @author alexeagle@google.com (Alex Eagle) */ public final class Es6InlineTypesNotYetParsedTest extends CompilerTestCase { private Compiler compiler; @Override public void setUp() { setAcceptedLanguage(LanguageMode.ECMASCRIPT_2015); compiler = createCompiler(); } @Override protected CompilerOptions getOptions() { CompilerOptions options = super.getOptions(); options.setLanguageOut(LanguageMode.ECMASCRIPT6_TYPED); options.setEmitUseStrict(true); return options; } @Override protected CompilerPass getProcessor(Compiler compiler) { return new JsdocToEs6TypedConverter(compiler); } @Override protected int getNumRepetitions() { return 1; } public void testNullType() { assertSource("/** @type {null} */ var n;") .transpilesTo("var n;"); } public void testUntypedVarargs() { assertSource("/** @param {function(this:T, ...)} fn */ function f(fn) {}") .transpilesTo("function f(fn: (...p1) => any) {\n}\n;"); } public void testAnyTypeVarargsParam() { assertSource("/** @param {...*} v */ function f(v){}") .transpilesTo("function f(...v: any[]) {\n}\n;"); } public void testUnionWithUndefined() { assertSource("/** @param {Object|undefined} v */ function f(v){}") .transpilesTo("function f(v: Object) {\n}\n;"); } public void testUnionWithNullAndUndefined() { assertSource("/** @param {null|undefined} v */ function f(v){}") .transpilesTo("function f(v) {\n}\n;"); } public void testFunctionType() { assertSource("/** @type {function(string,number):boolean} */ var n;") .transpilesTo("var n: (p1: string, p2: number) => boolean;"); } public void testTypeUnion() { assertSource("/** @type {(number|boolean)} */ var n;") .transpilesTo("var n: number | boolean;"); } public void testArrayType() { assertSource("/** @type {Array.<string>} */ var s;") .transpilesTo("var s: string[];"); assertSource("/** @type {!Array.<!$jscomp.typecheck.Checker>} */ var s;") .transpilesTo("var s: $jscomp.typecheck.Checker[];"); } public void testRecordType() { assertSource("/** @type {{myNum: number, myObject}} */ var s;") .transpilesTo("var s: {myNum:number, myObject};"); } public void testParameterizedType() { assertSource("/** @type {MyCollection.<string>} */ var s;") .transpilesTo("var s: MyCollection<string>;"); assertSource("/** @type {Object.<string, number>} */ var s;") .transpilesTo("var s: Object<string, number>;"); assertSource("/** @type {Object.<number>} */ var s;") .transpilesTo("var s: Object<any, number>;"); } public void testParameterizedTypeWithVoid() throws Exception { assertSource("/** @return {!goog.async.Deferred.<void>} */ f = function() {};") .transpilesTo("f = function(): goog.async.Deferred {\n};"); } public void testOptionalParameterTypeWithUndefined() throws Exception { assertSource("/** @param {(null|undefined)=} opt_ignored */ f = function(opt_ignored) {};") .transpilesTo("f = function(opt_ignored) {\n};"); } private SourceTranslationSubject assertSource(String... s) { return new SourceTranslationSubject(THROW_ASSERTION_ERROR, s); } private class SourceTranslationSubject extends Subject<SourceTranslationSubject, String[]> { public SourceTranslationSubject(FailureStrategy failureStrategy, String[] s) { super(failureStrategy, s); } private String doCompile(String... lines) { compiler.init( externsInputs, asList(SourceFile.fromCode("expected", LINE_JOINER.join(lines))), getOptions()); compiler.setErrorManager(new TestErrorManager()); Node root = compiler.parseInputs(); getProcessor(compiler).process(root.getFirstChild(), root.getLastChild()); return compiler.toSource(); } public void transpilesTo(String... lines) { assertThat(doCompile(actual()).trim()) .isEqualTo("'use strict';" + LINE_JOINER.join(lines)); } } }