All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.facebook.swift.generator.ConstantRenderer Maven / Gradle / Ivy

/*
 * Copyright (C) 2012 Facebook, 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.facebook.swift.generator;

import com.facebook.swift.parser.model.BaseType;
import com.facebook.swift.parser.model.Const;
import com.facebook.swift.parser.model.ConstIdentifier;
import com.facebook.swift.parser.model.ConstInteger;
import com.facebook.swift.parser.model.ConstList;
import com.facebook.swift.parser.model.ConstMap;
import com.facebook.swift.parser.model.ConstString;
import com.facebook.swift.parser.model.ConstValue;
import com.facebook.swift.parser.model.IdentifierType;
import com.facebook.swift.parser.model.ListType;
import com.facebook.swift.parser.model.MapType;
import com.facebook.swift.parser.model.SetType;
import com.facebook.swift.parser.model.ThriftType;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Shorts;

import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;

public class ConstantRenderer
{
    private final TypeToJavaConverter typeConverter;
    private final String defaultNamespace;
    private final TypeRegistry typeRegistry;
    private final TypedefRegistry typedefRegistry;

    public ConstantRenderer(
            TypeToJavaConverter typeConverter,
            String defaultNamespace,
            TypeRegistry typeRegistry,
            TypedefRegistry typedefRegistry)
    {
        this.typeConverter = typeConverter;
        this.defaultNamespace = defaultNamespace;
        this.typeRegistry = typeRegistry;
        this.typedefRegistry = typedefRegistry;
    }

    public String render(Const constant)
    {
        return render(constant.getType(), constant.getValue());
    }

    public String render(ThriftType thriftType, ConstValue value)
    {
        if (thriftType instanceof BaseType) {
            return renderBaseConstant((BaseType) thriftType, value);
        }
        else if (thriftType instanceof ListType) {
            checkArgument(value instanceof ConstList);
            return renderListConstant((ListType) thriftType, (ConstList) value);
        }
        else if (thriftType instanceof MapType) {
            checkArgument(value instanceof ConstMap);
            return renderMapType((MapType) thriftType, (ConstMap) value);
        }
        else if (thriftType instanceof SetType) {
            checkArgument(value instanceof ConstList);
            return renderSetConstant((SetType) thriftType, (ConstList) value);
        }
        else if (thriftType instanceof IdentifierType) {
            String typeName = ((IdentifierType) thriftType).getName();
            ThriftType resolvedType = typedefRegistry.findType(defaultNamespace, typeName);
            checkState(resolvedType != null, format("Could not resolve type named '%s'", typeName));
            return render(resolvedType, value);
        }
        else {
            throw new IllegalStateException("Not yet implemented");
        }
    }

    private String renderIdentifierType(IdentifierType identifierType, ConstIdentifier value)
    {
        return value.value();
    }

    private String renderMapType(MapType mapType, ConstMap value)
    {
        StringBuilder sb = new StringBuilder();

        sb.append("ImmutableMap.<");
        sb.append(typeConverter.convert(mapType.getKeyType(), false));
        sb.append(", ");
        sb.append(typeConverter.convert(mapType.getValueType(), false));
        sb.append(">builder()\n");

        Set> entries = value.value().entrySet();
        for (Map.Entry entry : entries) {
            if (entry.getKey() instanceof ConstIdentifier) {
                throw new IllegalStateException("Not yet implemented");
            }
            if (entry.getValue() instanceof ConstIdentifier) {
                throw new IllegalStateException("Not yet implemented");
            }
            sb.append(format("    .put(%s, %s)\n",
                             render(mapType.getKeyType(), entry.getKey()),
                             render(mapType.getValueType(), entry.getValue())));
        }
        sb.append("    .build()");

        return sb.toString();
    }

    private String renderListConstant(ListType listType, ConstList value)
    {
        StringBuilder sb = new StringBuilder();

        sb.append("ImmutableList.<");
        sb.append(typeConverter.convert(listType.getElementType(), false));
        sb.append(">builder()\n");

        List elements = value.value();
        for (ConstValue element : elements) {
            if (element instanceof ConstIdentifier) {
                throw new IllegalStateException("Not yet implemented");
            }
            sb.append(format("    .add(%s)\n", render(listType.getElementType(), element)));
        }
        sb.append("    .build()");

        return sb.toString();
    }

    private String renderSetConstant(SetType setType, ConstList value)
    {
        StringBuilder sb = new StringBuilder();

        sb.append("ImmutableSet.<");
        sb.append(typeConverter.convert(setType.getElementType(), false));
        sb.append(">builder()\n");

        List elements = value.value();
        for (ConstValue element : elements) {
            if (element instanceof ConstIdentifier) {
                throw new IllegalStateException("Not yet implemented");
            }
            sb.append(format("    .add(%s)\n", render(setType.getElementType(), element)));
        }
        sb.append("    .build()");

        return sb.toString();
    }

    private String renderBaseConstant(BaseType baseType, ConstValue value)
    {
        switch (baseType.getType()) {
            case BOOL:
            case BYTE:
            case I16:
            case I32:
            case I64:
                checkArgument(value instanceof ConstInteger);
                return renderIntegerConstant(baseType, (ConstInteger) value);

            case STRING:
                checkArgument(value instanceof ConstString);
                return "\"" + value.value() + "\"";

            case DOUBLE:
                // Allow auto-promotion of integer types
                checkArgument(value.value() instanceof Number);
                return Double.toString(((Number) value.value()).doubleValue());

            default:
                throw new IllegalArgumentException();
        }
    }

    private String renderIntegerConstant(BaseType baseType, ConstInteger value)
    {
        switch (baseType.getType()) {
            case BOOL:
                checkArgument(
                        value.value() == 0 || value.value() == 1,
                        "Bool constant out of range '" + value.value() + "' (must be 0 or 1)");
                return Boolean.toString(value.value() == 0 ? false : true);

            case BYTE:
                checkArgument(
                        value.value() >= Byte.MIN_VALUE && value.value() <= Byte.MAX_VALUE,
                        "Byte constant out of range: '" + value.value() + "'");
                return Byte.toString((byte) (long) value.value());

            case I16:
                return Short.toString(Shorts.checkedCast(value.value()));

            case I32:
                return Integer.toString(Ints.checkedCast(value.value()));

            case I64:
                return Long.toString(value.value()) + "L";

            default:
                throw new IllegalStateException();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy