Package com.google.javascript.jscomp

Source Code of com.google.javascript.jscomp.TypeValidatorTest

/*
* Copyright 2009 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.TypeValidator.TYPE_MISMATCH_WARNING;
import static com.google.javascript.rhino.jstype.JSTypeNative.BOOLEAN_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.NUMBER_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.STRING_TYPE;

import com.google.common.collect.Lists;
import com.google.javascript.jscomp.CheckLevel;
import com.google.javascript.jscomp.TypeValidator.TypeMismatch;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.jstype.JSType;
import com.google.javascript.rhino.jstype.JSTypeNative;
import com.google.javascript.rhino.jstype.JSTypeRegistry;

import java.util.Collections;
import java.util.List;

/**
* Tests for TypeValidator.
* @author nicksantos@google.com (Nick Santos)
*/
public class TypeValidatorTest extends CompilerTestCase {

  private Compiler compiler = null;

  public TypeValidatorTest() {
    enableTypeCheck(CheckLevel.ERROR);
  }

  @Override
  protected CompilerPass getProcessor(final Compiler compiler) {
    this.compiler = compiler;
    return new CompilerPass() {
      @Override
      public void process(Node externs, Node n) {
        // Do nothing: we're in it for the type-checking.
      }
    };
  }

  @Override public int getNumRepetitions() { return 1; }

  public void testBasicMismatch() throws Exception {
    testSame("/** @param {number} x */ function f(x) {} f('a');",
        TYPE_MISMATCH_WARNING);
    assertMismatches(Lists.newArrayList(fromNatives(STRING_TYPE, NUMBER_TYPE)));
  }

  public void testFunctionMismatch() throws Exception {
    testSame(
        "/** \n" +
        " * @param {function(string): number} x \n" +
        " * @return {function(boolean): string} \n" +
        " */ function f(x) { return x; }",
        TYPE_MISMATCH_WARNING);

    JSTypeRegistry registry = compiler.getTypeRegistry();
    JSType string = registry.getNativeType(STRING_TYPE);
    JSType bool = registry.getNativeType(BOOLEAN_TYPE);
    JSType number = registry.getNativeType(NUMBER_TYPE);
    JSType firstFunction = registry.createFunctionType(number, string);
    JSType secondFunction = registry.createFunctionType(string, bool);

    assertMismatches(
        Lists.newArrayList(
            new TypeMismatch(firstFunction, secondFunction, null),
            fromNatives(STRING_TYPE, BOOLEAN_TYPE),
            fromNatives(NUMBER_TYPE, STRING_TYPE)));
  }

  public void testFunctionMismatch2() throws Exception {
    testSame(
        "/** \n" +
        " * @param {function(string): number} x \n" +
        " * @return {function(boolean): number} \n" +
        " */ function f(x) { return x; }",
        TYPE_MISMATCH_WARNING);

    JSTypeRegistry registry = compiler.getTypeRegistry();
    JSType string = registry.getNativeType(STRING_TYPE);
    JSType bool = registry.getNativeType(BOOLEAN_TYPE);
    JSType number = registry.getNativeType(NUMBER_TYPE);
    JSType firstFunction = registry.createFunctionType(number, string);
    JSType secondFunction = registry.createFunctionType(number, bool);

    assertMismatches(
        Lists.newArrayList(
            new TypeMismatch(firstFunction, secondFunction, null),
            fromNatives(STRING_TYPE, BOOLEAN_TYPE)));
  }

  /**
   * Make sure the 'found' and 'required' strings are not identical when there is a mismatch.
   * See https://code.google.com/p/closure-compiler/issues/detail?id=719.
   */
  public void testFunctionMismatchLongTypes() throws Exception {
    testSame("",
        "/**\n" +
        " * @param {{a: string, b: string, c: string, d: string, e: string}} x\n" +
        " */\n" +
        "function f(x) {}\n" +
        "var y = {a:'',b:'',c:'',d:'',e:0};" +
        "f(y);",
        TYPE_MISMATCH_WARNING,
        "actual parameter 1 of f does not match formal parameter\n" +
        "found   : {a: string, b: string, c: string, d: string, e: (number|string)}\n" +
        "required: {a: string, b: string, c: string, d: string, e: string}");
  }

  /**
   * Same as testFunctionMismatchLongTypes, but with one of the types being a typedef.
   */
  public void testFunctionMismatchTypedef() throws Exception {
    testSame("",
        "/**\n" +
        " * @typedef {{a: string, b: string, c: string, d: string, e: string}}\n" +
        " */\n" +
        "var t;\n" +
        "/**\n" +
        " * @param {t} x\n" +
        " */\n" +
        "function f(x) {}\n" +
        "var y = {a:'',b:'',c:'',d:'',e:0};" +
        "f(y);",
        TYPE_MISMATCH_WARNING,
        "actual parameter 1 of f does not match formal parameter\n" +
        "found   : {a: string, b: string, c: string, d: string, e: (number|string)}\n" +
        "required: {a: string, b: string, c: string, d: string, e: string}");
  }

  public void testNullUndefined() {
    testSame("/** @param {string} x */ function f(x) {}\n" +
             "f(/** @type {string|null|undefined} */ ('a'));",
             TYPE_MISMATCH_WARNING);
    assertMismatches(Collections.<TypeMismatch>emptyList());
  }

  public void testSubclass() {
    testSame("/** @constructor */\n"  +
             "function Super() {}\n" +
             "/**\n" +
             " * @constructor\n" +
             " * @extends {Super}\n" +
             " */\n" +
             "function Sub() {}\n" +
             "/** @param {Sub} x */ function f(x) {}\n" +
             "f(/** @type {Super} */ (new Sub));",
             TYPE_MISMATCH_WARNING);
    assertMismatches(Collections.<TypeMismatch>emptyList());
  }

  private TypeMismatch fromNatives(JSTypeNative a, JSTypeNative b) {
    JSTypeRegistry registry = compiler.getTypeRegistry();
    return new TypeMismatch(
        registry.getNativeType(a), registry.getNativeType(b), null);
  }

  private void assertMismatches(List<TypeMismatch> expected) {
    List<TypeMismatch> actual = Lists.newArrayList(
        compiler.getTypeValidator().getMismatches());
    assertEquals(expected, actual);
  }
}
TOP

Related Classes of com.google.javascript.jscomp.TypeValidatorTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.