<commit_before>/*
 * Copyright 2020 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.shared.internal;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableListMultimap.flatteningToImmutableListMultimap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.base.CaseFormat;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor.JavaType;
import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
import com.google.template.soy.exprtree.ExprNode;
import com.google.template.soy.exprtree.GlobalNode;
import com.google.template.soy.exprtree.MethodCallNode;
import com.google.template.soy.exprtree.StringNode;
import com.google.template.soy.internal.proto.ProtoUtils;
import com.google.template.soy.shared.restricted.SoyMethod;
import com.google.template.soy.types.BoolType;
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.SoyTypes;
import java.util.Arrays;
import java.util.List;

/** Enum of built-in functions supported in Soy expressions. */
public enum BuiltinMethod implements SoyMethod {
  GET_EXTENSION("getExtension", 1) {
    @Override
    public boolean appliesToBase(SoyType baseType) {
      Preconditions.checkArgument(!SoyTypes.isNullable(baseType));
      return baseType.getKind() == SoyType.Kind.PROTO;
    }

    @Override
    public SoyType getReturnType(String methodName, SoyType baseType, List<ExprNode> params) {
      Preconditions.checkArgument(!SoyTypes.isNullable(baseType));
      Preconditions.checkArgument(params.size() == 1);
      SoyProtoType protoType = (SoyProtoType) baseType;
      ExprNode param = params.get(0);
      if (param instanceof GlobalNode) {
        String fieldName = ((GlobalNode) param).getName();
        if (protoType.getExtensionFieldNames().contains(fieldName)) {
          return protoType.getFieldType(fieldName);
        }
      }
      throw new IllegalArgumentException("Bad parameter " + param);
    }
  },

  HAS_PROTO_FIELD("has[X]", 0) {
    @Override
    public boolean appliesToBase(SoyType baseType) {
      Preconditions.checkArgument(!SoyTypes.isNullable(baseType));
      return baseType.getKind() == SoyType.Kind.PROTO;
    }

    @Override
    public boolean appliesTo(String methodName, SoyType baseType) {
      if (!appliesToBase(baseType)) {
        return false;
      }
      if (!matchesName(methodName)) {
        return false;
      }
      SoyProtoType protoType = (SoyProtoType) baseType;
      String fieldName = methodToFieldName(methodName);
      if (!protoType.getFieldNames().contains(fieldName)) {
        return false;
      }
      return acceptFieldDescriptor(protoType.getFieldDescriptor(fieldName));
    }

    private boolean acceptFieldDescriptor(FieldDescriptor fd) {
      if (fd.isExtension() || fd.isRepeated() || fd.getJavaType() == JavaType.MESSAGE) {
        return false;
      }
      if (fd.getFile().getSyntax() == Syntax.PROTO3) {
        // In proto3 only submessages and optional primitives have hassers.
        // TODO(user): Uncomment when new method lands in open source proto lib.
        // return fd.hasOptionalKeyword();
        return false;
      }

      return true;
    }

    @Override
    public SoyType getReturnType(String methodName, SoyType baseType, List<ExprNode> params) {
      return BoolType.getInstance();
    }

    boolean matchesName(String methodName) {
      if (methodName.length() <= 3) {
        return false;
      }
      if (!methodName.startsWith("has")) {
        return false;
      }
      char firstChar = methodName.charAt(3);
      return firstChar >= 'A' && firstChar <= 'Z';
    }

    @Override
    ImmutableCollection<String> expandMethodNames(SoyType baseType, List<SoyType> argTypes) {
      if (baseType.getKind() != Kind.PROTO) {
        return ImmutableList.of();
      }
      SoyProtoType protoType = (SoyProtoType) baseType;
      return protoType.getFieldNames().stream()<commit_msg>Enable presence for proto3 optional fields. This only enabled on []. OS is blocked waiting on some lib updates.<commit_after>/*
 * Copyright 2020 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.shared.internal;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableListMultimap.flatteningToImmutableListMultimap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.base.CaseFormat;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor.JavaType;
import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
import com.google.template.soy.exprtree.ExprNode;
import com.google.template.soy.exprtree.GlobalNode;
import com.google.template.soy.exprtree.MethodCallNode;
import com.google.template.soy.exprtree.StringNode;
import com.google.template.soy.internal.proto.ProtoUtils;
import com.google.template.soy.shared.restricted.SoyMethod;
import com.google.template.soy.types.BoolType;
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.SoyTypes;
import java.util.Arrays;
import java.util.List;

/** Enum of built-in functions supported in Soy expressions. */
public enum BuiltinMethod implements SoyMethod {
  GET_EXTENSION("getExtension", 1) {
    @Override
    public boolean appliesToBase(SoyType baseType) {
      Preconditions.checkArgument(!SoyTypes.isNullable(baseType));
      return baseType.getKind() == SoyType.Kind.PROTO;
    }

    @Override
    public SoyType getReturnType(String methodName, SoyType baseType, List<ExprNode> params) {
      Preconditions.checkArgument(!SoyTypes.isNullable(baseType));
      Preconditions.checkArgument(params.size() == 1);
      SoyProtoType protoType = (SoyProtoType) baseType;
      ExprNode param = params.get(0);
      if (param instanceof GlobalNode) {
        String fieldName = ((GlobalNode) param).getName();
        if (protoType.getExtensionFieldNames().contains(fieldName)) {
          return protoType.getFieldType(fieldName);
        }
      }
      throw new IllegalArgumentException("Bad parameter " + param);
    }
  },

  HAS_PROTO_FIELD("has[X]", 0) {
    @Override
    public boolean appliesToBase(SoyType baseType) {
      Preconditions.checkArgument(!SoyTypes.isNullable(baseType));
      return baseType.getKind() == SoyType.Kind.PROTO;
    }

    @Override
    public boolean appliesTo(String methodName, SoyType baseType) {
      if (!appliesToBase(baseType)) {
        return false;
      }
      if (!matchesName(methodName)) {
        return false;
      }
      SoyProtoType protoType = (SoyProtoType) baseType;
      String fieldName = methodToFieldName(methodName);
      if (!protoType.getFieldNames().contains(fieldName)) {
        return false;
      }
      return acceptFieldDescriptor(protoType.getFieldDescriptor(fieldName));
    }

    private boolean acceptFieldDescriptor(FieldDescriptor fd) {
      if (fd.isExtension() || fd.isRepeated() || fd.getJavaType() == JavaType.MESSAGE) {
        return false;
      }
      if (fd.getFile().getSyntax() == Syntax.PROTO3) {
        return false;
      }

      return true;
    }

    @Override
    public SoyType getReturnType(String methodName, SoyType baseType, List<ExprNode> params) {
      return BoolType.getInstance();
    }

    boolean matchesName(String methodName) {
      if (methodName.length() <= 3) {
        return false;
      }
      if (!methodName.startsWith("has")) {
        return false;
      }
      char firstChar = methodName.charAt(3);
      return firstChar >= 'A' && firstChar <= 'Z';
    }

    @Override
    ImmutableCollection<String> expandMethodNames(SoyType baseType, List<SoyType> argTypes) {
      if (baseType.getKind() != Kind.PROTO) {
        return ImmutableList.of();
      }
      SoyProtoType protoType = (SoyProtoType) baseType;
      return protoType.getFieldNames().stream()
{'fraction_non_alphanumeric': 0.10382401315789473, 'fraction_numerical': 0.003289473684210526, 'mean_word_length': 3.7551319648093844, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, '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': '5217791', 'n_tokens_mistral': 2821, 'n_tokens_neox': 2786, 'n_words': 640}