<commit_before>/*
 * Copyright 2016 Google Inc.
 *
 * 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.template.soy.jssrc.internal;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.template.soy.jssrc.dsl.Expression.stringLiteral;
import static com.google.template.soy.jssrc.internal.JsRuntime.ARRAY_IS_ARRAY;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_HTML_SAFE_ATTRIBUTE;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_HTML_SAFE_HTML;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_IS_FUNCTION;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_IS_OBJECT;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_SOY_DATA_SANITIZED_CONTENT;
import static com.google.template.soy.jssrc.internal.JsRuntime.SOY_ASSERT_PARAM_TYPE;
import static com.google.template.soy.jssrc.internal.JsRuntime.SOY_MAP_IS_SOY_MAP;
import static com.google.template.soy.jssrc.internal.JsRuntime.SOY_VELOG;
import static com.google.template.soy.jssrc.internal.JsRuntime.sanitizedContentType;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
import com.google.template.soy.base.SoyBackendKind;
import com.google.template.soy.base.internal.SanitizedContentKind;
import com.google.template.soy.base.internal.TemplateContentKind;
import com.google.template.soy.data.internalutils.NodeContentKinds;
import com.google.template.soy.jssrc.dsl.CodeChunk.Generator;
import com.google.template.soy.jssrc.dsl.Expression;
import com.google.template.soy.jssrc.dsl.GoogRequire;
import com.google.template.soy.types.LegacyObjectMapType;
import com.google.template.soy.types.ListType;
import com.google.template.soy.types.MapType;
import com.google.template.soy.types.RecordType;
import com.google.template.soy.types.SanitizedType;
import com.google.template.soy.types.SoyProtoEnumType;
import com.google.template.soy.types.SoyProtoType;
import com.google.template.soy.types.SoyType;
import com.google.template.soy.types.SoyType.Kind;
import com.google.template.soy.types.TemplateType;
import com.google.template.soy.types.UnionType;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * A representation of a javascript type.
 *
 * <p>This is geared toward generating jscompiler compatible type expressions for the purpose of
 * declarations and cast operators.
 */
public final class JsType {

  // TODO(lukes): use this consistently throughout jssrc.  We should consider inserting type
  // expressions when extracting list items/map items/record items.  Also at all of those points we
  // should strongly consider using the value coercion logic.  The fact that we don't leads to many
  // inconsistencies especially w.r.t. how sanitized proto fields are handled.

  // NOTE: currently we allow null for any/?, in theory we shouldn't but it isn't clear how useful
  // the non-nullable type declarations would be for users.

  private static final JsType ANY_TYPE =
      builder().addType("*").setPredicate(TypePredicate.NO_OP).build();

  private static final JsType UNKNOWN_TYPE =
      builder().addType("?").setPredicate(TypePredicate.NO_OP).build();

  private static final JsType BOOLEAN_TYPE =
      builder().addType("boolean").setPredicate(typeofTypePredicate("boolean")).build();

  private static final JsType NUMBER_TYPE =
      builder().addType("number").setPredicate(typeofTypePredicate("number")).build();

  private static final JsType STRING_TYPE =
      builder().addType("string").setPredicate(typeofTypePredicate("string")).build();

  private static final JsType MESSAGE_TYPE =
      builder()
          .addType("!jspb.Message")
          .setPredicate(
              (value, codeGenerator) ->
                  Optional.of(value.instanceOf(GoogRequire.create("jspb.Message").reference())))
          .addRequire(GoogRequire.create("jspb.Message"))
          .build();
  private static final JsType RAW_ARRAY_TYPE =
      builder().addType("!Array").setPredicate(ARRAY_IS_ARRAY).build();

  private static final JsType RAW_OBJECT_TYPE =
      builder().addType("!Object").setPredicate(GOOG_IS_OBJECT).build();

  private static final JsType NULL_OR_UNDEFINED_TYPE =
      builder()
          .addType("null")
          .addType("undefined")
          .setPredicate((value, codeGenerator) -> Optional.of(value.doubleEqualsNull()))
          .build();

  private static final ImmutableMap<SanitizedContentKind, JsType> SANITIZED_TYPES;
  private static final ImmutableMap<SanitizedContentKind, JsType> SANITIZED_TYPES_STRICT;

  private static final JsType IDOM_ATTRIBUTES =
      builder()
          .addType("function()")
          .addType("!google3.javascript.template.soy.element_lib_idom.IdomFunction")
          .addType("!goog.soy.data.SanitizedHtmlAttribute")
          .addRequire(
              GoogRequire.createTypeRequire("google3.javascript.template.soy.element_lib_idom"))
          .addRequire(GoogRequire.create("goog.soy.data.SanitizedHtmlAttribute"))
          .setPredicate(
              (value, codeGenerator) ->
                  Optional.of(
                      GOOG_IS_FUNCTION
                          .call(value)
                          .or(value.instanceOf(GOOG_HTML_SAFE_ATTRIBUTE), codeGenerator)))
          .build();

  private static final GoogRequire SANITIZED_CONTENT_KIND =
      GoogRequire.createWithAlias("goog.soy.data.SanitizedContentKind", "SanitizedContentKind");
  // This cannot use a goog.require() alias to avoid conflicts with legacy
  // FilterHtmlAttributesDirective
  private static final Expression IS_IDOM_FUNCTION_TYPE =
      GoogRequire.create("google3.javascript.template.soy.soyutils_directives")
          .googModuleGet()
          .dotAccess("$$isIdomFunctionType");

  private static final JsType LIT_HTML =
      builder()
          // Always require a thunk to simulate CallParamContent nodes.
          .addType("function():lit_element.TemplateResult")
          .addRequire(GoogRequire.createWithAlias("litElement", "lit_element"))
          .setPredicate(TypePredicate.NO_OP)
          .build();

  private static final JsType IDOM_HTML =
      builder()
          .addType("!goog.soy.data.SanitizedHtml")
          .addType("!goog.html.SafeHtml")
          .addRequire(GoogRequire.createTypeRequire("goog.html.SafeHtml"))
          .addRequire(GoogRequire.createTypeRequire("goog.soy.data.SanitizedHtml"))
          .addType("!google3.javascript.template.soy.element_lib_idom.IdomFunction")
          .addRequire(
              GoogRequire.createTypeRequire("google3.javascript.template.soy.element_lib_idom"))
          .addType("function(!incrementaldomlib.IncrementalDomRenderer): undefined")
          .addRequire(
              GoogRequire.createWithAlias(
                  "google3.javascript.template.soy.api_idom", "incrementaldomlib"))
          .setPredicate(
              (value, codeGenerator) ->
                  Optional.of(
                      IS_IDOM_FUNCTION_TYPE
                          .call(value, SANITIZED_CONTENT_KIND.dotAccess("HTML"))
                          .or(value.instanceOf(GOOG_HTML_SAFE_HTML), codeGenerator)
                          .or(value.instanceOf(GOOG_SOY_DATA_SANITIZED_CONTENT), codeGenerator)))<commit_msg>Allow template types to be usable from Wiz components.<commit_after>/*
 * Copyright 2016 Google Inc.
 *
 * 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.template.soy.jssrc.internal;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.template.soy.jssrc.dsl.Expression.stringLiteral;
import static com.google.template.soy.jssrc.internal.JsRuntime.ARRAY_IS_ARRAY;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_HTML_SAFE_ATTRIBUTE;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_HTML_SAFE_HTML;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_IS_FUNCTION;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_IS_OBJECT;
import static com.google.template.soy.jssrc.internal.JsRuntime.GOOG_SOY_DATA_SANITIZED_CONTENT;
import static com.google.template.soy.jssrc.internal.JsRuntime.SOY_ASSERT_PARAM_TYPE;
import static com.google.template.soy.jssrc.internal.JsRuntime.SOY_MAP_IS_SOY_MAP;
import static com.google.template.soy.jssrc.internal.JsRuntime.SOY_VELOG;
import static com.google.template.soy.jssrc.internal.JsRuntime.sanitizedContentType;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
import com.google.template.soy.base.SoyBackendKind;
import com.google.template.soy.base.internal.SanitizedContentKind;
import com.google.template.soy.base.internal.TemplateContentKind;
import com.google.template.soy.data.internalutils.NodeContentKinds;
import com.google.template.soy.jssrc.dsl.CodeChunk.Generator;
import com.google.template.soy.jssrc.dsl.Expression;
import com.google.template.soy.jssrc.dsl.GoogRequire;
import com.google.template.soy.types.LegacyObjectMapType;
import com.google.template.soy.types.ListType;
import com.google.template.soy.types.MapType;
import com.google.template.soy.types.RecordType;
import com.google.template.soy.types.SanitizedType;
import com.google.template.soy.types.SoyProtoEnumType;
import com.google.template.soy.types.SoyProtoType;
import com.google.template.soy.types.SoyType;
import com.google.template.soy.types.SoyType.Kind;
import com.google.template.soy.types.TemplateType;
import com.google.template.soy.types.UnionType;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * A representation of a javascript type.
 *
 * <p>This is geared toward generating jscompiler compatible type expressions for the purpose of
 * declarations and cast operators.
 */
public final class JsType {

  // TODO(lukes): use this consistently throughout jssrc.  We should consider inserting type
  // expressions when extracting list items/map items/record items.  Also at all of those points we
  // should strongly consider using the value coercion logic.  The fact that we don't leads to many
  // inconsistencies especially w.r.t. how sanitized proto fields are handled.

  // NOTE: currently we allow null for any/?, in theory we shouldn't but it isn't clear how useful
  // the non-nullable type declarations would be for users.

  private static final JsType ANY_TYPE =
      builder().addType("*").setPredicate(TypePredicate.NO_OP).build();

  private static final JsType UNKNOWN_TYPE =
      builder().addType("?").setPredicate(TypePredicate.NO_OP).build();

  private static final JsType BOOLEAN_TYPE =
      builder().addType("boolean").setPredicate(typeofTypePredicate("boolean")).build();

  private static final JsType NUMBER_TYPE =
      builder().addType("number").setPredicate(typeofTypePredicate("number")).build();

  private static final JsType STRING_TYPE =
      builder().addType("string").setPredicate(typeofTypePredicate("string")).build();

  private static final JsType MESSAGE_TYPE =
      builder()
          .addType("!jspb.Message")
          .setPredicate(
              (value, codeGenerator) ->
                  Optional.of(value.instanceOf(GoogRequire.create("jspb.Message").reference())))
          .addRequire(GoogRequire.create("jspb.Message"))
          .build();
  private static final JsType RAW_ARRAY_TYPE =
      builder().addType("!Array").setPredicate(ARRAY_IS_ARRAY).build();

  private static final JsType RAW_OBJECT_TYPE =
      builder().addType("!Object").setPredicate(GOOG_IS_OBJECT).build();

  private static final JsType NULL_OR_UNDEFINED_TYPE =
      builder()
          .addType("null")
          .addType("undefined")
          .setPredicate((value, codeGenerator) -> Optional.of(value.doubleEqualsNull()))
          .build();

  private static final ImmutableMap<SanitizedContentKind, JsType> SANITIZED_TYPES;
  private static final ImmutableMap<SanitizedContentKind, JsType> SANITIZED_TYPES_STRICT;

  private static final JsType IDOM_ATTRIBUTES =
      builder()
          .addType("function()")
          .addType("!google3.javascript.template.soy.element_lib_idom.IdomFunction")
          .addType("!goog.soy.data.SanitizedHtmlAttribute")
          .addRequire(
              GoogRequire.createTypeRequire("google3.javascript.template.soy.element_lib_idom"))
          .addRequire(GoogRequire.create("goog.soy.data.SanitizedHtmlAttribute"))
          .setPredicate(
              (value, codeGenerator) ->
                  Optional.of(
                      GOOG_IS_FUNCTION
                          .call(value)
                          .or(value.instanceOf(GOOG_HTML_SAFE_ATTRIBUTE), codeGenerator)))
          .build();

  private static final GoogRequire SANITIZED_CONTENT_KIND =
      GoogRequire.createWithAlias("goog.soy.data.SanitizedContentKind", "SanitizedContentKind");
  // This cannot use a goog.require() alias to avoid conflicts with legacy
  // FilterHtmlAttributesDirective
  private static final Expression IS_IDOM_FUNCTION_TYPE =
      GoogRequire.create("google3.javascript.template.soy.soyutils_directives")
          .googModuleGet()
          .dotAccess("$$isIdomFunctionType");

  private static final JsType LIT_HTML =
      builder()
          .addType("lit_element.TemplateResult")
          .addRequire(GoogRequire.createWithAlias("litElement", "lit_element"))
          .setPredicate(TypePredicate.NO_OP)
          .build();

  private static final JsType IDOM_HTML =
      builder()
          .addType("!goog.soy.data.SanitizedHtml")
          .addType("!goog.html.SafeHtml")
          .addRequire(GoogRequire.createTypeRequire("goog.html.SafeHtml"))
          .addRequire(GoogRequire.createTypeRequire("goog.soy.data.SanitizedHtml"))
          .addType("!google3.javascript.template.soy.element_lib_idom.IdomFunction")
          .addRequire(
              GoogRequire.createTypeRequire("google3.javascript.template.soy.element_lib_idom"))
          .addType("function(!incrementaldomlib.IncrementalDomRenderer): undefined")
          .addRequire(
              GoogRequire.createWithAlias(
                  "google3.javascript.template.soy.api_idom", "incrementaldomlib"))
          .setPredicate(
              (value, codeGenerator) ->
                  Optional.of(
                      IS_IDOM_FUNCTION_TYPE
                          .call(value, SANITIZED_CONTENT_KIND.dotAccess("HTML"))
                          .or(value.instanceOf(GOOG_HTML_SAFE_HTML), codeGenerator)
                          .or(value.instanceOf(GOOG_SOY_DATA_SANITIZED_CONTENT), codeGenerator)))
{'fraction_non_alphanumeric': 0.10314579552329099, 'fraction_numerical': 0.0016938898971566847, 'mean_word_length': 3.739392201834862, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6612254', 'n_tokens_mistral': 4959, 'n_tokens_neox': 4870, 'n_words': 935}